From f7be6d5c5bd5e2f8065d1dbdbaaceaf9ce9c7172 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Wed, 20 Dec 2023 07:30:30 +0200 Subject: [PATCH 001/200] work in progress, tons of optimizations --- LibSample/BroadcastTest.cs | 8 +- LibSample/EchoMessagesTest.cs | 8 +- LibSample/GithubSample.cs | 8 +- LibSample/HolePunchServerTest.cs | 2 +- LibSample/SpeedBench.cs | 2 +- LiteNetLib.Tests/LiteNetLib.Tests.csproj | 2 +- LiteNetLib/NativeSocket.cs | 13 +- LiteNetLib/NetManager.HashSet.cs | 205 ++++++++++++++++++++ LiteNetLib/NetManager.Socket.cs | 115 ++++++----- LiteNetLib/NetManager.cs | 51 ++--- LiteNetLib/NetPacket.cs | 4 + LiteNetLib/NetPeer.cs | 50 ++--- LiteNetLibSampleUnity/Assets/LiteNetLib.dll | Bin 105984 -> 108544 bytes LiteNetLibSampleUnity/Assets/LiteNetLib.xml | 12 +- 14 files changed, 336 insertions(+), 144 deletions(-) create mode 100644 LiteNetLib/NetManager.HashSet.cs diff --git a/LibSample/BroadcastTest.cs b/LibSample/BroadcastTest.cs index c51bdf9f..a59955c9 100644 --- a/LibSample/BroadcastTest.cs +++ b/LibSample/BroadcastTest.cs @@ -15,7 +15,7 @@ private class ClientListener : INetEventListener public void OnPeerConnected(NetPeer peer) { - Console.WriteLine("[Client {0}] connected to: {1}:{2}", Client.LocalPort, peer.EndPoint.Address, peer.EndPoint.Port); + Console.WriteLine("[Client {0}] connected to: {1}:{2}", Client.LocalPort, peer.Address, peer.Port); } public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) @@ -60,17 +60,17 @@ private class ServerListener : INetEventListener public void OnPeerConnected(NetPeer peer) { - Console.WriteLine("[Server] Peer connected: " + peer.EndPoint); + Console.WriteLine("[Server] Peer connected: " + peer); var peers = Server.ConnectedPeerList; foreach (var netPeer in peers) { - Console.WriteLine("ConnectedPeersList: id={0}, ep={1}", netPeer.Id, netPeer.EndPoint); + Console.WriteLine("ConnectedPeersList: id={0}, ep={1}", netPeer.Id, netPeer); } } public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { - Console.WriteLine("[Server] Peer disconnected: " + peer.EndPoint + ", reason: " + disconnectInfo.Reason); + Console.WriteLine("[Server] Peer disconnected: " + peer + ", reason: " + disconnectInfo.Reason); } public void OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) diff --git a/LibSample/EchoMessagesTest.cs b/LibSample/EchoMessagesTest.cs index 150a6379..7a8dc9b9 100644 --- a/LibSample/EchoMessagesTest.cs +++ b/LibSample/EchoMessagesTest.cs @@ -15,7 +15,7 @@ private class ClientListener : INetEventListener { public void OnPeerConnected(NetPeer peer) { - Console.WriteLine("[Client] connected to: {0}:{1}", peer.EndPoint.Address, peer.EndPoint.Port); + Console.WriteLine("[Client] connected to: {0}:{1}", peer.Address, peer.Port); NetDataWriter dataWriter = new NetDataWriter(); for (int i = 0; i < 5; i++) @@ -103,17 +103,17 @@ private class ServerListener : INetEventListener public void OnPeerConnected(NetPeer peer) { - Console.WriteLine("[Server] Peer connected: " + peer.EndPoint); + Console.WriteLine("[Server] Peer connected: " + peer); foreach (var netPeer in Server) { if(netPeer.ConnectionState == ConnectionState.Connected) - Console.WriteLine("ConnectedPeersList: id={0}, ep={1}", netPeer.Id, netPeer.EndPoint); + Console.WriteLine("ConnectedPeersList: id={0}, ep={1}", netPeer.Id, netPeer); } } public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { - Console.WriteLine("[Server] Peer disconnected: " + peer.EndPoint + ", reason: " + disconnectInfo.Reason); + Console.WriteLine("[Server] Peer disconnected: " + peer + ", reason: " + disconnectInfo.Reason); } public void OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) diff --git a/LibSample/GithubSample.cs b/LibSample/GithubSample.cs index 4bb8d389..0a680449 100644 --- a/LibSample/GithubSample.cs +++ b/LibSample/GithubSample.cs @@ -23,10 +23,10 @@ public void Server() listener.PeerConnectedEvent += peer => { - Console.WriteLine("We got connection: {0}", peer.EndPoint); // Show peer ip - NetDataWriter writer = new NetDataWriter(); // Create writer class - writer.Put("Hello client!"); // Put some string - peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability + Console.WriteLine("We got connection: {0}", peer); // Show peer ip + NetDataWriter writer = new NetDataWriter(); // Create writer class + writer.Put("Hello client!"); // Put some string + peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability }; while (!Console.KeyAvailable) diff --git a/LibSample/HolePunchServerTest.cs b/LibSample/HolePunchServerTest.cs index 2d81adee..d7564d56 100644 --- a/LibSample/HolePunchServerTest.cs +++ b/LibSample/HolePunchServerTest.cs @@ -91,7 +91,7 @@ public void Run() clientListener.PeerConnectedEvent += peer => { - Console.WriteLine("PeerConnected: " + peer.EndPoint); + Console.WriteLine("PeerConnected: " + peer); }; clientListener.ConnectionRequestEvent += request => diff --git a/LibSample/SpeedBench.cs b/LibSample/SpeedBench.cs index aa9a163f..09dcb5f4 100644 --- a/LibSample/SpeedBench.cs +++ b/LibSample/SpeedBench.cs @@ -69,7 +69,7 @@ void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, Ne void INetEventListener.OnPeerConnected(NetPeer peer) { - Console.WriteLine($"Server: client connected: {peer.EndPoint}"); + Console.WriteLine($"Server: client connected: {peer}"); } void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) diff --git a/LiteNetLib.Tests/LiteNetLib.Tests.csproj b/LiteNetLib.Tests/LiteNetLib.Tests.csproj index 9307007c..a948fce9 100644 --- a/LiteNetLib.Tests/LiteNetLib.Tests.csproj +++ b/LiteNetLib.Tests/LiteNetLib.Tests.csproj @@ -6,7 +6,7 @@ net6.0;net5.0;net471;netcoreapp3.1 - net6.0;net5.0;net471;netcoreapp3.1;net8.0 + net6.0;net8.0;netcoreapp3.1;net471 diff --git a/LiteNetLib/NativeSocket.cs b/LiteNetLib/NativeSocket.cs index fc846c8b..ff0f94d1 100644 --- a/LiteNetLib/NativeSocket.cs +++ b/LiteNetLib/NativeSocket.cs @@ -18,11 +18,11 @@ namespace LiteNetLib private readonly int _hash; - public NativeAddr(byte[] address, int len) + public NativeAddr(byte[] address) { _part1 = BitConverter.ToInt64(address, 0); _part2 = BitConverter.ToInt64(address, 8); - if (len > 16) + if (address.Length > 16) { _part3 = BitConverter.ToInt64(address, 16); _part4 = BitConverter.ToInt32(address, 24); @@ -69,9 +69,9 @@ public override bool Equals(object obj) internal class NativeEndPoint : IPEndPoint { - public readonly byte[] NativeAddress; + public byte[] NativeAddress; - public NativeEndPoint(byte[] address) : base(IPAddress.Any, 0) + public void SetNetAddress(byte[] address) { NativeAddress = new byte[address.Length]; Buffer.BlockCopy(address, 0, NativeAddress, 0, address.Length); @@ -103,6 +103,11 @@ public NativeEndPoint(byte[] address) : base(IPAddress.Any, 0) Address = new IPAddress(ipv4Addr); } } + + public NativeEndPoint() : base(IPAddress.Any, 0) + { + + } } internal static class NativeSocket diff --git a/LiteNetLib/NetManager.HashSet.cs b/LiteNetLib/NetManager.HashSet.cs new file mode 100644 index 00000000..45ed39af --- /dev/null +++ b/LiteNetLib/NetManager.HashSet.cs @@ -0,0 +1,205 @@ +using System; +using System.Net; + +namespace LiteNetLib +{ + //minimal hashset class from dotnet with some optimizations + public partial class NetManager + { + private const int MaxPrimeArrayLength = 0x7FFFFFC3; + private const int HashPrime = 101; + private const int Lower31BitMask = 0x7FFFFFFF; + private static readonly int[] Primes = + { + 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 + }; + + private static int HashSetGetPrime(int min) + { + foreach (int prime in Primes) + { + if (prime >= min) + return prime; + } + + // Outside of our predefined table. Compute the hard way. + for (int i = (min | 1); i < int.MaxValue; i += 2) + { + if (IsPrime(i) && ((i - 1) % HashPrime != 0)) + return i; + } + return min; + + bool IsPrime(int candidate) + { + if ((candidate & 1) != 0) + { + int limit = (int)Math.Sqrt(candidate); + for (int divisor = 3; divisor <= limit; divisor += 2) + { + if (candidate % divisor == 0) + return false; + } + return true; + } + return candidate == 2; + } + } + + private struct Slot + { + internal int HashCode; + internal int Next; + internal NetPeer Value; + } + + private int[] _buckets; + private Slot[] _slots; + private int _count; + private int _lastIndex; + private int _freeList; + + private void ClearPeerSet() + { + if (_lastIndex > 0) + { + Array.Clear(_slots, 0, _lastIndex); + Array.Clear(_buckets, 0, _buckets.Length); + _lastIndex = 0; + _count = 0; + _freeList = -1; + } + } + + private bool ContainsPeer(IPEndPoint item) + { + if (_buckets != null) + { + int hashCode = item.GetHashCode() & Lower31BitMask; + for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].Next) + { + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(item)) + return true; + } + } + return false; + } + + private bool RemovePeerFromSet(IPEndPoint item) + { + if (_buckets == null) + return false; + int hashCode = item.GetHashCode() & Lower31BitMask; + int bucket = hashCode % _buckets.Length; + int last = -1; + for (int i = _buckets[bucket] - 1; i >= 0; last = i, i = _slots[i].Next) + { + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(item)) + { + if (last < 0) + _buckets[bucket] = _slots[i].Next + 1; + else + _slots[last].Next = _slots[i].Next; + _slots[i].HashCode = -1; + _slots[i].Value = null; + _slots[i].Next = _freeList; + + _count--; + if (_count == 0) + { + _lastIndex = 0; + _freeList = -1; + } + else + { + _freeList = i; + } + return true; + } + } + return false; + } + + public bool TryGetPeer(IPEndPoint equalValue, out NetPeer actualValue) + { + if (_buckets != null) + { + int hashCode = equalValue.GetHashCode() & Lower31BitMask; + for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].Next) + { + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(equalValue)) + { + actualValue = _slots[i].Value; + return true; + } + } + } + actualValue = null; + return false; + } + + private bool AddPeerToSet(NetPeer value) + { + if (_buckets == null) + { + int size = HashSetGetPrime(0); + _buckets = new int[size]; + _slots = new Slot[size]; + } + + int hashCode = value.GetHashCode() & Lower31BitMask; + int bucket = hashCode % _buckets.Length; + for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].Next) + { + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(value)) + return false; + } + + int index; + if (_freeList >= 0) + { + index = _freeList; + _freeList = _slots[index].Next; + } + else + { + if (_lastIndex == _slots.Length) + { + //increase capacity + int newSize = 2 * _count; + newSize = (uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > _count + ? MaxPrimeArrayLength + : HashSetGetPrime(newSize); + + // Able to increase capacity; copy elements to larger array and rehash + Slot[] newSlots = new Slot[newSize]; + Array.Copy(_slots, 0, newSlots, 0, _lastIndex); + _buckets = new int[newSize]; + for (int i = 0; i < _lastIndex; i++) + { + int b = newSlots[i].HashCode % newSize; + newSlots[i].Next = _buckets[b] - 1; + _buckets[b] = i + 1; + } + _slots = newSlots; + // this will change during resize + bucket = hashCode % _buckets.Length; + } + index = _lastIndex; + _lastIndex++; + } + _slots[index].HashCode = hashCode; + _slots[index].Value = value; + _slots[index].Next = _buckets[bucket] - 1; + _buckets[bucket] = index + 1; + _count++; + + return true; + } + } + +} diff --git a/LiteNetLib/NetManager.Socket.cs b/LiteNetLib/NetManager.Socket.cs index 3acaf506..ba2910c0 100644 --- a/LiteNetLib/NetManager.Socket.cs +++ b/LiteNetLib/NetManager.Socket.cs @@ -21,13 +21,15 @@ public partial class NetManager private PausedSocketFix _pausedSocketFix; #endif +#if NET8_0_OR_GREATER + private SocketAddress _sockAddrCache = new SocketAddress(AddressFamily.InterNetworkV6); +#endif + #if !LITENETLIB_UNSAFE [ThreadStatic] private static byte[] _sendToBuffer; #endif [ThreadStatic] private static byte[] _endPointBuffer; - private readonly Dictionary _nativeAddrMap = new Dictionary(); - private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("ff02::1"); public static readonly bool IPv6Support; @@ -70,23 +72,6 @@ static NetManager() #endif } - private void RegisterEndPoint(IPEndPoint ep) - { - if (UseNativeSockets && ep is NativeEndPoint nep) - { - _nativeAddrMap.Add(new NativeAddr(nep.NativeAddress, nep.NativeAddress.Length), nep); - } - } - - private void UnregisterEndPoint(IPEndPoint ep) - { - if (UseNativeSockets && ep is NativeEndPoint nep) - { - var nativeAddr = new NativeAddr(nep.NativeAddress, nep.NativeAddress.Length); - _nativeAddrMap.Remove(nativeAddr); - } - } - private bool ProcessError(SocketException ex) { switch (ex.SocketErrorCode) @@ -102,6 +87,7 @@ private bool ProcessError(SocketException ex) case SocketError.MessageSize: case SocketError.TimedOut: case SocketError.NetworkReset: + case SocketError.WouldBlock: //NetDebug.Write($"[R]Ignored error: {(int)ex.SocketErrorCode} - {ex}"); break; default: @@ -141,62 +127,36 @@ private void ManualReceive(Socket socket, EndPoint bufferEndPoint) } } - private bool NativeReceiveFrom(ref NetPacket packet, IntPtr s, byte[] addrBuffer, int addrSize) - { - //Reading data - packet.Size = NativeSocket.RecvFrom(s, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize); - if (packet.Size == 0) - return true; //socket closed or empty packet - - if (packet.Size == -1) - { - var errorCode = NativeSocket.GetSocketError(); - //Linux timeout EAGAIN - return errorCode == SocketError.WouldBlock || errorCode == SocketError.TimedOut || ProcessError(new SocketException((int)errorCode)) == false; - } - - var nativeAddr = new NativeAddr(addrBuffer, addrSize); - if (!_nativeAddrMap.TryGetValue(nativeAddr, out var endPoint)) - endPoint = new NativeEndPoint(addrBuffer); - - //All ok! - //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}"); - OnMessageReceived(packet, endPoint); - packet = PoolGetPacket(NetConstants.MaxPacketSize); - return true; - } - private void NativeReceiveLogic() { IntPtr socketHandle4 = _udpSocketv4.Handle; IntPtr socketHandle6 = _udpSocketv6?.Handle ?? IntPtr.Zero; byte[] addrBuffer4 = new byte[NativeSocket.IPv4AddrSize]; byte[] addrBuffer6 = new byte[NativeSocket.IPv6AddrSize]; - int addrSize4 = addrBuffer4.Length; - int addrSize6 = addrBuffer6.Length; var selectReadList = new List(2); var socketv4 = _udpSocketv4; var socketV6 = _udpSocketv6; var packet = PoolGetPacket(NetConstants.MaxPacketSize); + var nativeEndPointCache = new NativeEndPoint(); while (IsRunning) { if (socketV6 == null) { - if (NativeReceiveFrom(ref packet, socketHandle4, addrBuffer4, addrSize4) == false) + if (NativeReceiveFrom(socketHandle4, addrBuffer4) == false) return; continue; } bool messageReceived = false; if (socketv4.Available != 0 || selectReadList.Contains(socketv4)) { - if (NativeReceiveFrom(ref packet, socketHandle4, addrBuffer4, addrSize4) == false) + if (NativeReceiveFrom(socketHandle4, addrBuffer4) == false) return; messageReceived = true; } if (socketV6.Available != 0 || selectReadList.Contains(socketV6)) { - if (NativeReceiveFrom(ref packet, socketHandle6, addrBuffer6, addrSize6) == false) + if (NativeReceiveFrom(socketHandle6, addrBuffer6) == false) return; messageReceived = true; } @@ -233,13 +193,41 @@ private void NativeReceiveLogic() NetDebug.WriteError("[NM] SocketReceiveThread error: " + e ); } } + + bool NativeReceiveFrom(IntPtr s, byte[] addrBuffer) + { + //Reading data + int addrSize = addrBuffer.Length; + packet.Size = NativeSocket.RecvFrom(s, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize); + if (packet.Size == 0) + return true; //socket closed or empty packet + + if (packet.Size == -1) + { + //Linux timeout EAGAIN + return ProcessError(new SocketException((int)NativeSocket.GetSocketError())) == false; + } + + //All ok! + //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}"); + nativeEndPointCache.SetNetAddress(addrBuffer); + OnMessageReceived(packet, nativeEndPointCache); + packet = PoolGetPacket(NetConstants.MaxPacketSize); + return true; + } } private void ReceiveFrom(Socket s, ref EndPoint bufferEndPoint) { var packet = PoolGetPacket(NetConstants.MaxPacketSize); - packet.Size = s.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); +#if NET8_0_OR_GREATER + packet.Size = s.ReceiveFrom(packet, SocketFlags.None, _sockAddrCache); + OnMessageReceived(packet, (IPEndPoint)bufferEndPoint.Create(_sockAddrCache)); +#else + packet.Size = + s.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); OnMessageReceived(packet, (IPEndPoint)bufferEndPoint); +#endif } private void ReceiveLogic() @@ -610,15 +598,19 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd case SocketError.HostUnreachable: case SocketError.NetworkUnreachable: - if (DisconnectOnUnreachable && TryGetPeer(remoteEndPoint, out var fromPeer)) + if (DisconnectOnUnreachable) { - DisconnectPeerForce( - fromPeer, - ex.SocketErrorCode == SocketError.HostUnreachable - ? DisconnectReason.HostUnreachable - : DisconnectReason.NetworkUnreachable, - ex.SocketErrorCode, - null); + _peersLock.EnterReadLock(); + TryGetPeer(remoteEndPoint, out var fromPeer); + _peersLock.ExitReadLock(); + if(fromPeer != null) + DisconnectPeerForce( + fromPeer, + ex.SocketErrorCode == SocketError.HostUnreachable + ? DisconnectReason.HostUnreachable + : DisconnectReason.NetworkUnreachable, + ex.SocketErrorCode, + null); } CreateEvent(NetEvent.EType.Error, remoteEndPoint: remoteEndPoint, errorCode: ex.SocketErrorCode); @@ -711,6 +703,13 @@ public bool SendBroadcast(byte[] data, int start, int length, int port) new IPEndPoint(MulticastAddressV6, port)) > 0; } } + catch (SocketException ex) + { + if (ex.SocketErrorCode == SocketError.HostUnreachable) + return false; + NetDebug.WriteError($"[S][MCAST] {ex}"); + return broadcastSuccess; + } catch (Exception ex) { NetDebug.WriteError($"[S][MCAST] {ex}"); diff --git a/LiteNetLib/NetManager.cs b/LiteNetLib/NetManager.cs index 6f21107f..2b4fec42 100644 --- a/LiteNetLib/NetManager.cs +++ b/LiteNetLib/NetManager.cs @@ -89,19 +89,6 @@ public NetEvent(NetManager manager) /// public partial class NetManager : IEnumerable { - private class IPEndPointComparer : IEqualityComparer - { - public bool Equals(IPEndPoint x, IPEndPoint y) - { - return x.Address.Equals(y.Address) && x.Port == y.Port; - } - - public int GetHashCode(IPEndPoint obj) - { - return obj.GetHashCode(); - } - } - public struct NetPeerEnumerator : IEnumerator { private readonly NetPeer _initialPeer; @@ -158,9 +145,8 @@ private struct IncomingData private readonly INtpEventListener _ntpEventListener; private readonly IPeerAddressChangedListener _peerAddressChangedListener; - private readonly Dictionary _peersDict = new Dictionary(new IPEndPointComparer()); - private readonly Dictionary _requestsDict = new Dictionary(new IPEndPointComparer()); - private readonly ConcurrentDictionary _ntpRequests = new ConcurrentDictionary(new IPEndPointComparer()); + private readonly Dictionary _requestsDict = new Dictionary(); + private readonly ConcurrentDictionary _ntpRequests = new ConcurrentDictionary(); private readonly ReaderWriterLockSlim _peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); private volatile NetPeer _headPeer; private int _connectedPeersCount; @@ -384,7 +370,6 @@ public NetPeer GetPeerById(int id) public bool TryGetPeerById(int id, out NetPeer peer) { peer = GetPeerById(id); - return peer != null; } @@ -395,14 +380,6 @@ public bool TryGetPeerById(int id, out NetPeer peer) public int ExtraPacketSizeForLayer => _extraPacketLayer?.ExtraPacketSizeForLayer ?? 0; - private bool TryGetPeer(IPEndPoint endPoint, out NetPeer peer) - { - _peersLock.EnterReadLock(); - bool result = _peersDict.TryGetValue(endPoint, out peer); - _peersLock.ExitReadLock(); - return result; - } - private void AddPeer(NetPeer peer) { _peersLock.EnterWriteLock(); @@ -412,7 +389,7 @@ private void AddPeer(NetPeer peer) _headPeer.PrevPeer = peer; } _headPeer = peer; - _peersDict.Add(peer.EndPoint, peer); + AddPeerToSet(peer); if (peer.Id >= _peersArray.Length) { int newSize = _peersArray.Length * 2; @@ -421,7 +398,6 @@ private void AddPeer(NetPeer peer) Array.Resize(ref _peersArray, newSize); } _peersArray[peer.Id] = peer; - RegisterEndPoint(peer.EndPoint); _peersLock.ExitWriteLock(); } @@ -434,7 +410,7 @@ private void RemovePeer(NetPeer peer) private void RemovePeerInternal(NetPeer peer) { - if (!_peersDict.Remove(peer.EndPoint)) + if (!RemovePeerFromSet(peer)) return; if (peer == _headPeer) _headPeer = peer.NextPeer; @@ -447,7 +423,6 @@ private void RemovePeerInternal(NetPeer peer) _peersArray[peer.Id] = null; _peerIds.Enqueue(peer.Id); - UnregisterEndPoint(peer.EndPoint); } /// @@ -609,13 +584,13 @@ private void ProcessEvent(NetEvent evt) case NetEvent.EType.PeerAddressChanged: _peersLock.EnterUpgradeableReadLock(); IPEndPoint previousAddress = null; - if (_peersDict.ContainsKey(evt.Peer.EndPoint)) + if (ContainsPeer(evt.Peer)) { _peersLock.EnterWriteLock(); - _peersDict.Remove(evt.Peer.EndPoint); - previousAddress = evt.Peer.EndPoint; + RemovePeerFromSet(evt.Peer); + previousAddress = evt.Peer; evt.Peer.FinishEndPointChange(evt.RemoteEndPoint); - _peersDict.Add(evt.Peer.EndPoint, evt.Peer); + AddPeerToSet(evt.Peer); _peersLock.ExitWriteLock(); } _peersLock.ExitUpgradeableReadLock(); @@ -791,7 +766,7 @@ internal NetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData else { _peersLock.EnterUpgradeableReadLock(); - if (_peersDict.TryGetValue(request.RemoteEndPoint, out netPeer)) + if (TryGetPeer(request.RemoteEndPoint, out netPeer)) { //already have peer _peersLock.ExitUpgradeableReadLock(); @@ -810,7 +785,7 @@ internal NetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData AddPeer(netPeer); _peersLock.ExitUpgradeableReadLock(); CreateEvent(NetEvent.EType.Connect, netPeer); - NetDebug.Write(NetLogLevel.Trace, $"[NM] Received peer connection Id: {netPeer.ConnectTime}, EP: {netPeer.EndPoint}"); + NetDebug.Write(NetLogLevel.Trace, $"[NM] Received peer connection Id: {netPeer.ConnectTime}, EP: {netPeer}"); } } @@ -1000,7 +975,7 @@ private void DebugMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) //Check normal packets _peersLock.EnterReadLock(); - bool peerFound = _peersDict.TryGetValue(remoteEndPoint, out var netPeer); + bool peerFound = TryGetPeer(remoteEndPoint, out var netPeer); _peersLock.ExitReadLock(); if (peerFound && EnableStatistics) @@ -1621,7 +1596,7 @@ public NetPeer Connect(IPEndPoint target, NetDataWriter connectionData) byte connectionNumber = 0; _peersLock.EnterUpgradeableReadLock(); - if (_peersDict.TryGetValue(target, out var peer)) + if (TryGetPeer(target, out var peer)) { switch (peer.ConnectionState) { @@ -1684,7 +1659,7 @@ public void Stop(bool sendDisconnectMessages) //clear peers _peersLock.EnterWriteLock(); _headPeer = null; - _peersDict.Clear(); + ClearPeerSet(); _peersArray = new NetPeer[32]; _peersLock.ExitWriteLock(); _peerIds = new ConcurrentQueue(); diff --git a/LiteNetLib/NetPacket.cs b/LiteNetLib/NetPacket.cs index 4b403084..c1505d61 100644 --- a/LiteNetLib/NetPacket.cs +++ b/LiteNetLib/NetPacket.cs @@ -156,5 +156,9 @@ public bool Verify() bool fragmented = (RawData[0] & 0x80) != 0; return Size >= headerSize && (!fragmented || Size >= headerSize + NetConstants.FragmentHeaderSize); } + + #if LITENETLIB_SPANS || NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || NETCOREAPP2_1 || NETCOREAPP3_1 || NET5_0 || NETSTANDARD2_1 + public static implicit operator Span(NetPacket p) => new Span(p.RawData, 0, p.Size); + #endif } } diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index a9cfb24b..94d2fec5 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -50,7 +50,7 @@ internal enum ShutdownResult /// /// Network peer. Main purpose is sending messages to specific peer. /// - public class NetPeer + public class NetPeer : IPEndPoint { //Ping and RTT private int _rtt; @@ -114,7 +114,6 @@ private class IncomingFragments private int _mergeCount; //Connection - private IPEndPoint _remoteEndPoint; private int _connectAttempts; private int _connectTimer; private long _connectTime; @@ -128,11 +127,6 @@ private class IncomingFragments private readonly NetPacket _connectRequestPacket; private readonly NetPacket _connectAcceptPacket; - /// - /// Peer ip address and port - /// - public IPEndPoint EndPoint => _remoteEndPoint; - /// /// Peer parent NetManager /// @@ -201,14 +195,21 @@ private class IncomingFragments /// public readonly NetStatistics Statistics; + private SocketAddress _cachedSocketAddr; + + public override SocketAddress Serialize() + { + return _cachedSocketAddr ?? (_cachedSocketAddr = base.Serialize()); + } + //incoming connection constructor - internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id) + internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id) : base(remoteEndPoint.Address, remoteEndPoint.Port) { Id = id; Statistics = new NetStatistics(); NetManager = netManager; ResetMtu(); - _remoteEndPoint = remoteEndPoint; + _connectionState = ConnectionState.Connected; _mergeData = new NetPacket(PacketProperty.Merged, NetConstants.MaxPacketSize); _pongPacket = new NetPacket(PacketProperty.Pong, 0); @@ -233,7 +234,8 @@ internal void FinishEndPointChange(IPEndPoint newEndPoint) if (_connectionState != ConnectionState.EndPointChange) return; _connectionState = ConnectionState.Connected; - _remoteEndPoint = newEndPoint; + Address = newEndPoint.Address; + Port = newEndPoint.Port; } internal void ResetMtu() @@ -357,7 +359,7 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte _connectRequestPacket.ConnectionNumber = connectNum; //Send request - NetManager.SendRaw(_connectRequestPacket, _remoteEndPoint); + NetManager.SendRaw(_connectRequestPacket, this); NetDebug.Write(NetLogLevel.Trace, $"[CC] ConnectId: {_connectTime}, ConnectNum: {connectNum}"); } @@ -377,7 +379,7 @@ internal NetPeer(NetManager netManager, ConnectionRequest request, int id) _connectionState = ConnectionState.Connected; //Send - NetManager.SendRaw(_connectAcceptPacket, _remoteEndPoint); + NetManager.SendRaw(_connectAcceptPacket, this); NetDebug.Write(NetLogLevel.Trace, $"[CC] ConnectId: {_connectTime}"); } @@ -873,7 +875,7 @@ internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) } _connectionState = ConnectionState.ShutdownRequested; NetDebug.Write("[Peer] Send disconnect"); - NetManager.SendRaw(_shutdownPacket, _remoteEndPoint); + NetManager.SendRaw(_shutdownPacket, this); return result; } } @@ -997,7 +999,7 @@ private void ProcessMtuPacket(NetPacket packet) _mtuCheckAttempts = 0; NetDebug.Write("[MTU] check. send back: " + receivedMtu); packet.Property = PacketProperty.MtuOk; - NetManager.SendRawAndRecycle(packet, _remoteEndPoint); + NetManager.SendRawAndRecycle(packet, this); } else if(receivedMtu > _mtu && !_finishMtu) //MtuOk { @@ -1047,7 +1049,7 @@ private void UpdateMtuLogic(int deltaTime) FastBitConverter.GetBytes(p.RawData, p.Size - 4, newMtu);//and end of packet //Must check result for MTU fix - if (NetManager.SendRawAndRecycle(p, _remoteEndPoint) <= 0) + if (NetManager.SendRawAndRecycle(p, this) <= 0) _finishMtu = true; } } @@ -1067,7 +1069,7 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn //slow rare case check if (connRequest.ConnectionTime == _connectTime) { - var remoteBytes = _remoteEndPoint.Serialize(); + var remoteBytes = this.Serialize(); var localBytes = connRequest.TargetAddress; for (int i = remoteBytes.Size-1; i >= 0; i--) { @@ -1085,7 +1087,7 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn if (connRequest.ConnectionTime == _connectTime) { //just reply accept - NetManager.SendRaw(_connectAcceptPacket, _remoteEndPoint); + NetManager.SendRaw(_connectAcceptPacket, this); } //New connect request else if (connRequest.ConnectionTime > _connectTime) @@ -1158,7 +1160,7 @@ internal void ProcessPacket(NetPacket packet) NetDebug.Write("[PP]Ping receive, send pong"); FastBitConverter.GetBytes(_pongPacket.RawData, 3, DateTime.UtcNow.Ticks); _pongPacket.Sequence = packet.Sequence; - NetManager.SendRaw(_pongPacket, _remoteEndPoint); + NetManager.SendRaw(_pongPacket, this); } NetManager.PoolRecycle(packet); break; @@ -1216,12 +1218,12 @@ private void SendMerged() if (_mergeCount > 1) { NetDebug.Write("[P]Send merged: " + _mergePos + ", count: " + _mergeCount); - bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, _remoteEndPoint); + bytesSent = NetManager.SendRaw(_mergeData.RawData, 0, NetConstants.HeaderSize + _mergePos, this); } else { //Send without length information and merging - bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, _remoteEndPoint); + bytesSent = NetManager.SendRaw(_mergeData.RawData, NetConstants.HeaderSize + 2, _mergePos - 2, this); } if (NetManager.EnableStatistics) @@ -1242,7 +1244,7 @@ internal void SendUserData(NetPacket packet) if (mergedPacketSize + sizeTreshold >= _mtu) { NetDebug.Write(NetLogLevel.Trace, "[P]SendingPacket: " + packet.Property); - int bytesSent = NetManager.SendRaw(packet, _remoteEndPoint); + int bytesSent = NetManager.SendRaw(packet, this); if (NetManager.EnableStatistics) { @@ -1287,7 +1289,7 @@ internal void Update(int deltaTime) if (_shutdownTimer >= ShutdownDelay) { _shutdownTimer = 0; - NetManager.SendRaw(_shutdownPacket, _remoteEndPoint); + NetManager.SendRaw(_shutdownPacket, this); } } return; @@ -1305,7 +1307,7 @@ internal void Update(int deltaTime) } //else send connect again - NetManager.SendRaw(_connectRequestPacket, _remoteEndPoint); + NetManager.SendRaw(_connectRequestPacket, this); } return; @@ -1326,7 +1328,7 @@ internal void Update(int deltaTime) if (_pingTimer.IsRunning) UpdateRoundTripTime((int)_pingTimer.ElapsedMilliseconds); _pingTimer.Restart(); - NetManager.SendRaw(_pingPacket, _remoteEndPoint); + NetManager.SendRaw(_pingPacket, this); } //RTT - round trip time diff --git a/LiteNetLibSampleUnity/Assets/LiteNetLib.dll b/LiteNetLibSampleUnity/Assets/LiteNetLib.dll index a9708ee27933e7b7af0fbe552f010ee4f6074ad0..7b7607d47ba80eaa40dc7e67cfa1ebabdad10a4a 100644 GIT binary patch literal 108544 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 ZJJ*pO-r@5s6EsC{YPkOY=l4zm{|kbn+8O`= diff --git a/LiteNetLibSampleUnity/Assets/LiteNetLib.xml b/LiteNetLibSampleUnity/Assets/LiteNetLib.xml index 89d8b5f6..2b4ec2b9 100644 --- a/LiteNetLibSampleUnity/Assets/LiteNetLib.xml +++ b/LiteNetLibSampleUnity/Assets/LiteNetLib.xml @@ -260,6 +260,13 @@ Enables socket option "ReuseAddress" for specific purposes + +

+ UDP Only Socket Option + Normally IP sockets send packets of data through routers and gateways until they reach the final destination. + If the DontRoute flag is set to True, then data will be delivered on the local subnet only. + + Statistics of all connections @@ -738,11 +745,6 @@ Network peer. Main purpose is sending messages to specific peer. - - - Peer ip address and port - - Peer parent NetManager From f4b0fc4022d9351ec62b15b0a144c50df1220b56 Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 10:54:20 +0200 Subject: [PATCH 002/200] wip2 --- LibSample/LibSample.csproj | 2 +- LiteNetLib.Tests/CommunicationTest.cs | 4 +- LiteNetLib/NativeSocket.cs | 69 +-- LiteNetLib/NetManager.HashSet.cs | 121 +++- LiteNetLib/NetManager.Socket.cs | 122 ++-- LiteNetLib/NetManager.cs | 137 +---- LiteNetLib/NetPeer.cs | 40 +- LiteNetLib/Utils/FastBitConverter.cs | 4 +- docs/api/LiteNetLib.Layers.Crc32cLayer.html | 11 +- .../LiteNetLib.Layers.PacketLayerBase.html | 9 +- .../LiteNetLib.Layers.XorEncryptLayer.html | 11 +- docs/api/LiteNetLib.NetManager.html | 192 +++++-- docs/api/LiteNetLib.NetPacketReader.html | 54 ++ docs/api/LiteNetLib.NetPeer.html | 115 +++- docs/api/LiteNetLib.Utils.NetDataReader.html | 524 ++++++++++++++++++ .../LiteNetLib.Utils.PreserveAttribute.html | 243 ++++++++ docs/api/LiteNetLib.Utils.html | 3 + docs/api/toc.html | 3 + docs/manifest.json | 12 +- docs/xrefmap.yml | 314 +++++++++-- 20 files changed, 1560 insertions(+), 430 deletions(-) create mode 100644 docs/api/LiteNetLib.Utils.PreserveAttribute.html diff --git a/LibSample/LibSample.csproj b/LibSample/LibSample.csproj index 5ca608ac..f349b274 100644 --- a/LibSample/LibSample.csproj +++ b/LibSample/LibSample.csproj @@ -4,7 +4,7 @@ Exe net6.0;net5.0;netcoreapp3.1 net6.0;net5.0;net471;netcoreapp3.1 - net6.0;net5.0;net8.0;net471;netcoreapp3.1 + net6.0;net8.0;netcoreapp3.1;net471 diff --git a/LiteNetLib.Tests/CommunicationTest.cs b/LiteNetLib.Tests/CommunicationTest.cs index b2cbc88e..5d4c3619 100644 --- a/LiteNetLib.Tests/CommunicationTest.cs +++ b/LiteNetLib.Tests/CommunicationTest.cs @@ -683,7 +683,7 @@ public void ManualMode() server.Stop(); } - [Test] + [Test, Timeout(TestTimeout)] public void SendRawDataToAll() { var clientCount = 10; @@ -725,7 +725,7 @@ public void SendRawDataToAll() Assert.AreEqual(server.ConnectedPeersCount, clientCount); for (ushort i = 1; i <= clientCount; i++) { - Assert.AreEqual(ManagerStack.Client(i).ConnectedPeersCount, 1); + Assert.AreEqual(1, ManagerStack.Client(i).ConnectedPeersCount); Assert.That(data, Is.EqualTo(dataStack.Pop()).AsCollection); } } diff --git a/LiteNetLib/NativeSocket.cs b/LiteNetLib/NativeSocket.cs index ff0f94d1..171f48b6 100644 --- a/LiteNetLib/NativeSocket.cs +++ b/LiteNetLib/NativeSocket.cs @@ -7,75 +7,20 @@ namespace LiteNetLib { - internal readonly struct NativeAddr : IEquatable + internal class NativeEndPoint : IPEndPoint { - //common parts - private readonly long _part1; //family, port, etc - private readonly long _part2; - //ipv6 parts - private readonly long _part3; - private readonly int _part4; - - private readonly int _hash; - - public NativeAddr(byte[] address) - { - _part1 = BitConverter.ToInt64(address, 0); - _part2 = BitConverter.ToInt64(address, 8); - if (address.Length > 16) - { - _part3 = BitConverter.ToInt64(address, 16); - _part4 = BitConverter.ToInt32(address, 24); - } - else - { - _part3 = 0; - _part4 = 0; - } - _hash = (int)(_part1 >> 32) ^ (int)_part1 ^ - (int)(_part2 >> 32) ^ (int)_part2 ^ - (int)(_part3 >> 32) ^ (int)_part3 ^ - _part4; - } - - public override int GetHashCode() - { - return _hash; - } - - public bool Equals(NativeAddr other) - { - return _part1 == other._part1 && - _part2 == other._part2 && - _part3 == other._part3 && - _part4 == other._part4; - } - - public override bool Equals(object obj) - { - return obj is NativeAddr other && Equals(other); - } - - public static bool operator ==(NativeAddr left, NativeAddr right) - { - return left.Equals(right); - } + public byte[] NativeAddress; - public static bool operator !=(NativeAddr left, NativeAddr right) + public void CopyNativeAddress() { - return !left.Equals(right); + var tempAddr = new byte[NativeAddress.Length]; + Buffer.BlockCopy(NativeAddress, 0, tempAddr, 0, NativeAddress.Length); + NativeAddress = tempAddr; } - } - - internal class NativeEndPoint : IPEndPoint - { - public byte[] NativeAddress; public void SetNetAddress(byte[] address) { - NativeAddress = new byte[address.Length]; - Buffer.BlockCopy(address, 0, NativeAddress, 0, address.Length); - + NativeAddress = address; short family = (short)((address[1] << 8) | address[0]); Port =(ushort)((address[2] << 8) | address[3]); diff --git a/LiteNetLib/NetManager.HashSet.cs b/LiteNetLib/NetManager.HashSet.cs index 45ed39af..944fb2be 100644 --- a/LiteNetLib/NetManager.HashSet.cs +++ b/LiteNetLib/NetManager.HashSet.cs @@ -1,5 +1,6 @@ using System; using System.Net; +using System.Threading; namespace LiteNetLib { @@ -61,10 +62,15 @@ private struct Slot private Slot[] _slots; private int _count; private int _lastIndex; - private int _freeList; + private int _freeList = -1; + private NetPeer[] _peersArray = new NetPeer[32]; + private readonly ReaderWriterLockSlim _peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); + private volatile NetPeer _headPeer; private void ClearPeerSet() { + _peersLock.EnterWriteLock(); + _headPeer = null; if (_lastIndex > 0) { Array.Clear(_slots, 0, _lastIndex); @@ -73,9 +79,11 @@ private void ClearPeerSet() _count = 0; _freeList = -1; } + _peersArray = new NetPeer[32]; + _peersLock.ExitWriteLock(); } - private bool ContainsPeer(IPEndPoint item) + private bool ContainsPeer(NetPeer item) { if (_buckets != null) { @@ -89,16 +97,83 @@ private bool ContainsPeer(IPEndPoint item) return false; } - private bool RemovePeerFromSet(IPEndPoint item) + /// + /// Gets peer by peer id + /// + /// id of peer + /// Peer if peer with id exist, otherwise null + public NetPeer GetPeerById(int id) + { + return id >= 0 && id < _peersArray.Length ? _peersArray[id] : null; + } + + /// + /// Gets peer by peer id + /// + /// id of peer + /// resulting peer + /// True if peer with id exist, otherwise false + public bool TryGetPeerById(int id, out NetPeer peer) + { + peer = GetPeerById(id); + return peer != null; + } + + private void AddPeer(NetPeer peer) + { + _peersLock.EnterWriteLock(); + if (_headPeer != null) + { + peer.NextPeer = _headPeer; + _headPeer.PrevPeer = peer; + } + _headPeer = peer; + AddPeerToSet(peer); + if (peer.Id >= _peersArray.Length) + { + int newSize = _peersArray.Length * 2; + while (peer.Id >= newSize) + newSize *= 2; + Array.Resize(ref _peersArray, newSize); + } + _peersArray[peer.Id] = peer; + _peersLock.ExitWriteLock(); + } + + private void RemovePeer(NetPeer peer) + { + _peersLock.EnterWriteLock(); + RemovePeerInternal(peer); + _peersLock.ExitWriteLock(); + } + + private void RemovePeerInternal(NetPeer peer) + { + if (!RemovePeerFromSet(peer)) + 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); + } + + private bool RemovePeerFromSet(NetPeer peer) { if (_buckets == null) return false; - int hashCode = item.GetHashCode() & Lower31BitMask; + int hashCode = peer.GetHashCode() & Lower31BitMask; int bucket = hashCode % _buckets.Length; int last = -1; for (int i = _buckets[bucket] - 1; i >= 0; last = i, i = _slots[i].Next) { - if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(item)) + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(peer)) { if (last < 0) _buckets[bucket] = _slots[i].Next + 1; @@ -124,19 +199,49 @@ private bool RemovePeerFromSet(IPEndPoint item) return false; } - public bool TryGetPeer(IPEndPoint equalValue, out NetPeer actualValue) + private bool TryGetPeer(IPEndPoint endPoint, out NetPeer actualValue) + { + if (_buckets != null) + { +#if NET8_0_OR_GREATER + //can be NetPeer or IPEndPoint + int hashCode = endPoint.Serialize().GetHashCode() & Lower31BitMask; +#else + int hashCode = endPoint.GetHashCode() & Lower31BitMask; +#endif + _peersLock.EnterReadLock(); + for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].Next) + { + if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(endPoint)) + { + actualValue = _slots[i].Value; + _peersLock.ExitReadLock(); + return true; + } + } + _peersLock.ExitReadLock(); + } + actualValue = null; + return false; + } + + //only used for NET8 + private bool TryGetPeer(SocketAddress saddr, out NetPeer actualValue) { if (_buckets != null) { - int hashCode = equalValue.GetHashCode() & Lower31BitMask; + int hashCode = saddr.GetHashCode() & Lower31BitMask; + _peersLock.EnterReadLock(); for (int i = _buckets[hashCode % _buckets.Length] - 1; i >= 0; i = _slots[i].Next) { - if (_slots[i].HashCode == hashCode && _slots[i].Value.Equals(equalValue)) + if (_slots[i].HashCode == hashCode && _slots[i].Value.Serialize().Equals(saddr)) { actualValue = _slots[i].Value; + _peersLock.ExitReadLock(); return true; } } + _peersLock.ExitReadLock(); } actualValue = null; return false; diff --git a/LiteNetLib/NetManager.Socket.cs b/LiteNetLib/NetManager.Socket.cs index ba2910c0..b3a7b56c 100644 --- a/LiteNetLib/NetManager.Socket.cs +++ b/LiteNetLib/NetManager.Socket.cs @@ -22,14 +22,10 @@ public partial class NetManager #endif #if NET8_0_OR_GREATER - private SocketAddress _sockAddrCache = new SocketAddress(AddressFamily.InterNetworkV6); + private readonly SocketAddress _sockAddrCacheV4 = new SocketAddress(AddressFamily.InterNetwork); + private readonly SocketAddress _sockAddrCacheV6 = new SocketAddress(AddressFamily.InterNetworkV6); #endif -#if !LITENETLIB_UNSAFE - [ThreadStatic] private static byte[] _sendToBuffer; -#endif - [ThreadStatic] private static byte[] _endPointBuffer; - private const int SioUdpConnreset = -1744830452; //SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12 private static readonly IPAddress MulticastAddressV6 = IPAddress.Parse("ff02::1"); public static readonly bool IPv6Support; @@ -133,11 +129,11 @@ private void NativeReceiveLogic() IntPtr socketHandle6 = _udpSocketv6?.Handle ?? IntPtr.Zero; byte[] addrBuffer4 = new byte[NativeSocket.IPv4AddrSize]; byte[] addrBuffer6 = new byte[NativeSocket.IPv6AddrSize]; + var tempEndPoint = new NativeEndPoint(); var selectReadList = new List(2); var socketv4 = _udpSocketv4; var socketV6 = _udpSocketv6; var packet = PoolGetPacket(NetConstants.MaxPacketSize); - var nativeEndPointCache = new NativeEndPoint(); while (IsRunning) { @@ -210,8 +206,18 @@ bool NativeReceiveFrom(IntPtr s, byte[] addrBuffer) //All ok! //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}"); - nativeEndPointCache.SetNetAddress(addrBuffer); - OnMessageReceived(packet, nativeEndPointCache); + tempEndPoint.SetNetAddress(addrBuffer); + if (TryGetPeer(tempEndPoint, out var peer)) + { + //use cached native ep + OnMessageReceived(packet, peer); + } + else + { + tempEndPoint.CopyNativeAddress(); + OnMessageReceived(packet, tempEndPoint); + tempEndPoint = new NativeEndPoint(); + } packet = PoolGetPacket(NetConstants.MaxPacketSize); return true; } @@ -221,11 +227,11 @@ private void ReceiveFrom(Socket s, ref EndPoint bufferEndPoint) { var packet = PoolGetPacket(NetConstants.MaxPacketSize); #if NET8_0_OR_GREATER - packet.Size = s.ReceiveFrom(packet, SocketFlags.None, _sockAddrCache); - OnMessageReceived(packet, (IPEndPoint)bufferEndPoint.Create(_sockAddrCache)); + var sockAddr = s.AddressFamily == AddressFamily.InterNetwork ? _sockAddrCacheV4 : _sockAddrCacheV6; + packet.Size = s.ReceiveFrom(packet, SocketFlags.None, sockAddr); + OnMessageReceived(packet, TryGetPeer(sockAddr, out var peer) ? peer : (IPEndPoint)bufferEndPoint.Create(sockAddr)); #else - packet.Size = - s.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); + packet.Size = s.ReceiveFrom(packet.RawData, 0, NetConstants.MaxPacketSize, SocketFlags.None, ref bufferEndPoint); OnMessageReceived(packet, (IPEndPoint)bufferEndPoint); #endif } @@ -337,9 +343,7 @@ public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool m if (BindSocket(_udpSocketv6, new IPEndPoint(addressIPv6, LocalPort))) { if (_manualMode) - { _bufferEndPointv6 = new IPEndPoint(IPAddress.IPv6Any, 0); - } } else { @@ -513,75 +517,23 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd int result; try { - if (UseNativeSockets) + if (UseNativeSockets && remoteEndPoint is NetPeer peer) { - byte[] socketAddress; - - if (remoteEndPoint is NativeEndPoint nep) - { - socketAddress = nep.NativeAddress; - } - else //Convert endpoint to raw - { - if (_endPointBuffer == null) - _endPointBuffer = new byte[NativeSocket.IPv6AddrSize]; - socketAddress = _endPointBuffer; - - bool ipv4 = remoteEndPoint.AddressFamily == AddressFamily.InterNetwork; - short addressFamily = NativeSocket.GetNativeAddressFamily(remoteEndPoint); - - socketAddress[0] = (byte) (addressFamily); - socketAddress[1] = (byte) (addressFamily >> 8); - socketAddress[2] = (byte) (remoteEndPoint.Port >> 8); - socketAddress[3] = (byte) (remoteEndPoint.Port); - - if (ipv4) - { -#pragma warning disable 618 - long addr = remoteEndPoint.Address.Address; -#pragma warning restore 618 - socketAddress[4] = (byte) (addr); - socketAddress[5] = (byte) (addr >> 8); - socketAddress[6] = (byte) (addr >> 16); - socketAddress[7] = (byte) (addr >> 24); - } - else - { -#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER - remoteEndPoint.Address.TryWriteBytes(new Span(socketAddress, 8, 16), out _); -#else - byte[] addrBytes = remoteEndPoint.Address.GetAddressBytes(); - Buffer.BlockCopy(addrBytes, 0, socketAddress, 8, 16); -#endif - } - } - -#if LITENETLIB_UNSAFE unsafe { fixed (byte* dataWithOffset = &message[start]) - { - result = - NativeSocket.SendTo(socket.Handle, dataWithOffset, length, socketAddress, socketAddress.Length); - } - } -#else - if (start > 0) - { - if (_sendToBuffer == null) - _sendToBuffer = new byte[NetConstants.MaxPacketSize]; - Buffer.BlockCopy(message, start, _sendToBuffer, 0, length); - message = _sendToBuffer; + result = NativeSocket.SendTo(socket.Handle, dataWithOffset, length, peer.NativeAddress, peer.NativeAddress.Length); } - - result = NativeSocket.SendTo(socket.Handle, message, length, socketAddress, socketAddress.Length); -#endif if (result == -1) throw NativeSocket.GetSocketException(); } else { +#if NET8_0_OR_GREATER + result = socket.SendTo(new ReadOnlySpan(message, start, length), SocketFlags.None, remoteEndPoint.Serialize()); +#else result = socket.SendTo(message, start, length, SocketFlags.None, remoteEndPoint); +#endif } //NetDebug.WriteForce("[S]Send packet to {0}, result: {1}", remoteEndPoint, result); } @@ -598,19 +550,15 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd case SocketError.HostUnreachable: case SocketError.NetworkUnreachable: - if (DisconnectOnUnreachable) + if (DisconnectOnUnreachable && remoteEndPoint is NetPeer peer) { - _peersLock.EnterReadLock(); - TryGetPeer(remoteEndPoint, out var fromPeer); - _peersLock.ExitReadLock(); - if(fromPeer != null) - DisconnectPeerForce( - fromPeer, - ex.SocketErrorCode == SocketError.HostUnreachable - ? DisconnectReason.HostUnreachable - : DisconnectReason.NetworkUnreachable, - ex.SocketErrorCode, - null); + DisconnectPeerForce( + peer, + ex.SocketErrorCode == SocketError.HostUnreachable + ? DisconnectReason.HostUnreachable + : DisconnectReason.NetworkUnreachable, + ex.SocketErrorCode, + null); } CreateEvent(NetEvent.EType.Error, remoteEndPoint: remoteEndPoint, errorCode: ex.SocketErrorCode); @@ -633,9 +581,7 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd finally { if (expandedPacket != null) - { PoolRecycle(expandedPacket); - } } if (result <= 0) @@ -706,7 +652,7 @@ public bool SendBroadcast(byte[] data, int start, int length, int port) catch (SocketException ex) { if (ex.SocketErrorCode == SocketError.HostUnreachable) - return false; + return broadcastSuccess; NetDebug.WriteError($"[S][MCAST] {ex}"); return broadcastSuccess; } diff --git a/LiteNetLib/NetManager.cs b/LiteNetLib/NetManager.cs index 2b4fec42..1e373cb9 100644 --- a/LiteNetLib/NetManager.cs +++ b/LiteNetLib/NetManager.cs @@ -147,11 +147,8 @@ private struct IncomingData private readonly Dictionary _requestsDict = new Dictionary(); private readonly ConcurrentDictionary _ntpRequests = new ConcurrentDictionary(); - private readonly ReaderWriterLockSlim _peersLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion); - private volatile NetPeer _headPeer; private int _connectedPeersCount; private readonly List _connectedPeerListCache = new List(); - private NetPeer[] _peersArray = new NetPeer[32]; private readonly PacketLayerBase _extraPacketLayer; private int _lastPeerId; private ConcurrentQueue _peerIds = new ConcurrentQueue(); @@ -346,33 +343,6 @@ public List ConnectedPeerList } } - /// - /// Gets peer by peer id - /// - /// id of peer - /// Peer if peer with id exist, otherwise null - public NetPeer GetPeerById(int id) - { - if (id >= 0 && id < _peersArray.Length) - { - return _peersArray[id]; - } - - return null; - } - - /// - /// Gets peer by peer id - /// - /// id of peer - /// resulting peer - /// True if peer with id exist, otherwise false - public bool TryGetPeerById(int id, out NetPeer peer) - { - peer = GetPeerById(id); - return peer != null; - } - /// /// Returns connected peers count /// @@ -380,51 +350,6 @@ public bool TryGetPeerById(int id, out NetPeer peer) public int ExtraPacketSizeForLayer => _extraPacketLayer?.ExtraPacketSizeForLayer ?? 0; - private void AddPeer(NetPeer peer) - { - _peersLock.EnterWriteLock(); - if (_headPeer != null) - { - peer.NextPeer = _headPeer; - _headPeer.PrevPeer = peer; - } - _headPeer = peer; - AddPeerToSet(peer); - if (peer.Id >= _peersArray.Length) - { - int newSize = _peersArray.Length * 2; - while (peer.Id >= newSize) - newSize *= 2; - Array.Resize(ref _peersArray, newSize); - } - _peersArray[peer.Id] = peer; - _peersLock.ExitWriteLock(); - } - - private void RemovePeer(NetPeer peer) - { - _peersLock.EnterWriteLock(); - RemovePeerInternal(peer); - _peersLock.ExitWriteLock(); - } - - private void RemovePeerInternal(NetPeer peer) - { - if (!RemovePeerFromSet(peer)) - 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); - } - /// /// NetManager constructor /// @@ -588,7 +513,7 @@ private void ProcessEvent(NetEvent evt) { _peersLock.EnterWriteLock(); RemovePeerFromSet(evt.Peer); - previousAddress = evt.Peer; + previousAddress = new IPEndPoint(evt.Peer.Address, evt.Peer.Port); evt.Peer.FinishEndPointChange(evt.RemoteEndPoint); AddPeerToSet(evt.Peer); _peersLock.ExitWriteLock(); @@ -762,35 +687,31 @@ internal NetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData Buffer.BlockCopy(rejectData, start, shutdownPacket.RawData, 9, length); SendRawAndRecycle(shutdownPacket, request.RemoteEndPoint); } + lock (_requestsDict) + _requestsDict.Remove(request.RemoteEndPoint); } - else + else lock (_requestsDict) { - _peersLock.EnterUpgradeableReadLock(); if (TryGetPeer(request.RemoteEndPoint, out netPeer)) { //already have peer - _peersLock.ExitUpgradeableReadLock(); } else if (request.Result == ConnectionRequestResult.Reject) { netPeer = new NetPeer(this, request.RemoteEndPoint, GetNextPeerId()); netPeer.Reject(request.InternalPacket, rejectData, start, length); AddPeer(netPeer); - _peersLock.ExitUpgradeableReadLock(); NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject."); } else //Accept { netPeer = new NetPeer(this, request, GetNextPeerId()); AddPeer(netPeer); - _peersLock.ExitUpgradeableReadLock(); CreateEvent(NetEvent.EType.Connect, netPeer); NetDebug.Write(NetLogLevel.Trace, $"[NM] Received peer connection Id: {netPeer.ConnectTime}, EP: {netPeer}"); } - } - - lock(_requestsDict) _requestsDict.Remove(request.RemoteEndPoint); + } return netPeer; } @@ -974,9 +895,7 @@ private void DebugMessageReceived(NetPacket packet, IPEndPoint remoteEndPoint) } //Check normal packets - _peersLock.EnterReadLock(); - bool peerFound = TryGetPeer(remoteEndPoint, out var netPeer); - _peersLock.ExitReadLock(); + bool peerFound = remoteEndPoint is NetPeer netPeer || TryGetPeer(remoteEndPoint, out netPeer); if (peerFound && EnableStatistics) { @@ -1592,32 +1511,28 @@ public NetPeer Connect(IPEndPoint target, NetDataWriter connectionData) { if (_requestsDict.ContainsKey(target)) return null; - } - byte connectionNumber = 0; - _peersLock.EnterUpgradeableReadLock(); - if (TryGetPeer(target, out var peer)) - { - switch (peer.ConnectionState) + byte connectionNumber = 0; + if (TryGetPeer(target, out var peer)) { - //just return already connected peer - case ConnectionState.Connected: - case ConnectionState.Outgoing: - _peersLock.ExitUpgradeableReadLock(); - return peer; + switch (peer.ConnectionState) + { + //just return already connected peer + case ConnectionState.Connected: + case ConnectionState.Outgoing: + return peer; + } + //else reconnect + connectionNumber = (byte)((peer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber); + RemovePeer(peer); } - //else reconnect - connectionNumber = (byte)((peer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber); - RemovePeer(peer); - } - //Create reliable connection - //And send connection request - peer = new NetPeer(this, target, GetNextPeerId(), connectionNumber, connectionData); - AddPeer(peer); - _peersLock.ExitUpgradeableReadLock(); - - return peer; + //Create reliable connection + //And send connection request + peer = new NetPeer(this, target, GetNextPeerId(), connectionNumber, connectionData); + AddPeer(peer); + return peer; + } } /// @@ -1657,11 +1572,7 @@ public void Stop(bool sendDisconnectMessages) } //clear peers - _peersLock.EnterWriteLock(); - _headPeer = null; ClearPeerSet(); - _peersArray = new NetPeer[32]; - _peersLock.ExitWriteLock(); _peerIds = new ConcurrentQueue(); _lastPeerId = 0; #if DEBUG diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index 94d2fec5..4d7a2b56 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -196,10 +196,23 @@ private class IncomingFragments public readonly NetStatistics Statistics; private SocketAddress _cachedSocketAddr; + private int _cachedHashCode; + internal byte[] NativeAddress; + + /// + /// IPEndPoint serialize + /// + /// SocketAddress public override SocketAddress Serialize() { - return _cachedSocketAddr ?? (_cachedSocketAddr = base.Serialize()); + return _cachedSocketAddr; + } + + public override int GetHashCode() + { + //uses SocketAddress hash in NET8 and IPEndPoint hash for NativeSockets and previous NET versions + return _cachedHashCode; } //incoming connection constructor @@ -208,6 +221,16 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id) : bas Id = id; Statistics = new NetStatistics(); NetManager = netManager; + + if (NetManager.UseNativeSockets && remoteEndPoint is NativeEndPoint nep) + NativeAddress = nep.NativeAddress; + _cachedSocketAddr = base.Serialize(); +#if NET8_0_OR_GREATER + _cachedHashCode = NetManager.UseNativeSockets ? base.GetHashCode() : _cachedSocketAddr.GetHashCode(); +#else + _cachedHashCode = base.GetHashCode(); +#endif + ResetMtu(); _connectionState = ConnectionState.Connected; @@ -234,8 +257,18 @@ internal void FinishEndPointChange(IPEndPoint newEndPoint) if (_connectionState != ConnectionState.EndPointChange) return; _connectionState = ConnectionState.Connected; + Address = newEndPoint.Address; Port = newEndPoint.Port; + + if (NetManager.UseNativeSockets && newEndPoint is NativeEndPoint nep) + NativeAddress = nep.NativeAddress; + _cachedSocketAddr = base.Serialize(); +#if NET8_0_OR_GREATER + _cachedHashCode = NetManager.UseNativeSockets ? base.GetHashCode() : _cachedSocketAddr.GetHashCode(); +#else + _cachedHashCode = base.GetHashCode(); +#endif } internal void ResetMtu() @@ -1069,11 +1102,10 @@ internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket conn //slow rare case check if (connRequest.ConnectionTime == _connectTime) { - var remoteBytes = this.Serialize(); var localBytes = connRequest.TargetAddress; - for (int i = remoteBytes.Size-1; i >= 0; i--) + for (int i = _cachedSocketAddr.Size-1; i >= 0; i--) { - byte rb = remoteBytes[i]; + byte rb = _cachedSocketAddr[i]; if (rb == localBytes[i]) continue; if (rb < localBytes[i]) diff --git a/LiteNetLib/Utils/FastBitConverter.cs b/LiteNetLib/Utils/FastBitConverter.cs index 3ecd10c7..82bedf4e 100644 --- a/LiteNetLib/Utils/FastBitConverter.cs +++ b/LiteNetLib/Utils/FastBitConverter.cs @@ -6,7 +6,7 @@ namespace LiteNetLib.Utils { public static class FastBitConverter { -#if (LITENETLIB_UNSAFE || LITENETLIB_UNSAFELIB || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER) && !BIGENDIAN +#if (LITENETLIB_UNSAFE || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER) && !BIGENDIAN #if LITENETLIB_UNSAFE [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged @@ -14,7 +14,7 @@ public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) whe int size = sizeof(T); if (bytes.Length < startIndex + size) ThrowIndexOutOfRangeException(); -#if LITENETLIB_UNSAFELIB || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER +#if NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER Unsafe.As(ref bytes[startIndex]) = value; #else fixed (byte* ptr = &bytes[startIndex]) diff --git a/docs/api/LiteNetLib.Layers.Crc32cLayer.html b/docs/api/LiteNetLib.Layers.Crc32cLayer.html index 6a0f6853..ce524723 100644 --- a/docs/api/LiteNetLib.Layers.Crc32cLayer.html +++ b/docs/api/LiteNetLib.Layers.Crc32cLayer.html @@ -110,12 +110,12 @@

Methods -

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int)

+

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int)

Declaration
-
public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length)
+
public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int length)
Parameters
@@ -137,11 +137,6 @@
Parameters
- - - - - @@ -150,7 +145,7 @@
Parameters
data
intoffset
int length
Overrides
- + diff --git a/docs/api/LiteNetLib.Layers.PacketLayerBase.html b/docs/api/LiteNetLib.Layers.PacketLayerBase.html index abbeb9ad..e9e061bb 100644 --- a/docs/api/LiteNetLib.Layers.PacketLayerBase.html +++ b/docs/api/LiteNetLib.Layers.PacketLayerBase.html @@ -148,12 +148,12 @@

Methods -

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int)

+

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int)

Declaration
-
public abstract void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length)
+
public abstract void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int length)
Parameters
@@ -175,11 +175,6 @@
Parameters
- - - - - diff --git a/docs/api/LiteNetLib.Layers.XorEncryptLayer.html b/docs/api/LiteNetLib.Layers.XorEncryptLayer.html index 08e13b04..9918dfd5 100644 --- a/docs/api/LiteNetLib.Layers.XorEncryptLayer.html +++ b/docs/api/LiteNetLib.Layers.XorEncryptLayer.html @@ -164,12 +164,12 @@

Methods -

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int)

+

ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int)

Declaration
-
public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int offset, ref int length)
+
public override void ProcessInboundPacket(ref IPEndPoint endPoint, ref byte[] data, ref int length)
Parameters
data
intoffset
int length
@@ -191,11 +191,6 @@
Parameters
- - - - - @@ -204,7 +199,7 @@
Parameters
data
intoffset
int length
Overrides
- + diff --git a/docs/api/LiteNetLib.NetManager.html b/docs/api/LiteNetLib.NetManager.html index 52c330bc..ffd90695 100644 --- a/docs/api/LiteNetLib.NetManager.html +++ b/docs/api/LiteNetLib.NetManager.html @@ -259,6 +259,33 @@
Field Value
+

DontRoute

+

UDP Only Socket Option +Normally IP sockets send packets of data through routers and gateways until they reach the final destination. +If the DontRoute flag is set to True, then data will be delivered on the local subnet only.

+
+
+
Declaration
+
+
public bool DontRoute
+
+
Field Value
+ + + + + + + + + + + + + +
TypeDescription
bool
+ +

EnableStatistics

Toggles the collection of network statistics for the instance and all known peers

@@ -2603,6 +2630,129 @@
Parameters
+ +

SendToAll(ReadOnlySpan<byte>, DeliveryMethod, NetPeer)

+

Send data to all connected peers (channel - 0)

+
+
+
Declaration
+
+
public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options, NetPeer excludePeer)
+
+
Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescription
ReadOnlySpan<byte>data

Data

+
DeliveryMethodoptions

Send options (reliable, unreliable, etc.)

+
NetPeerexcludePeer

Excluded peer

+
+ + + +

SendToAll(ReadOnlySpan<byte>, DeliveryMethod)

+

Send data to all connected peers (channel - 0)

+
+
+
Declaration
+
+
public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options)
+
+
Parameters
+ + + + + + + + + + + + + + + + + + + + +
TypeNameDescription
ReadOnlySpan<byte>data

Data

+
DeliveryMethodoptions

Send options (reliable, unreliable, etc.)

+
+ + + +

SendToAll(ReadOnlySpan<byte>, byte, DeliveryMethod, NetPeer)

+

Send data to all connected peers

+
+
+
Declaration
+
+
public void SendToAll(ReadOnlySpan<byte> data, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
+
+
Parameters
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeNameDescription
ReadOnlySpan<byte>data

Data

+
bytechannelNumber

Number of channel (from 0 to channelsCount - 1)

+
DeliveryMethodoptions

Send options (reliable, unreliable, etc.)

+
NetPeerexcludePeer

Excluded peer

+
+ +

SendUnconnectedMessage(NetDataWriter, IPEndPoint)

Send message without connection

@@ -2827,48 +2977,6 @@
Returns
- -

SocketActive(bool)

-
-
-
Declaration
-
-
public bool SocketActive(bool ipv4)
-
-
Parameters
- - - - - - - - - - - - - - - -
TypeNameDescription
boolipv4
-
Returns
- - - - - - - - - - - - - -
TypeDescription
bool
- -

Start()

Start logic thread and listening on available port

diff --git a/docs/api/LiteNetLib.NetPacketReader.html b/docs/api/LiteNetLib.NetPacketReader.html index 94c97ef5..00602912 100644 --- a/docs/api/LiteNetLib.NetPacketReader.html +++ b/docs/api/LiteNetLib.NetPacketReader.html @@ -122,6 +122,57 @@
Inherited Members
+ + + + + + + + + + + + + + + + + @@ -215,6 +266,9 @@
Inherited Members
+ diff --git a/docs/api/LiteNetLib.NetPeer.html b/docs/api/LiteNetLib.NetPeer.html index cb4a8588..40b7f38e 100644 --- a/docs/api/LiteNetLib.NetPeer.html +++ b/docs/api/LiteNetLib.NetPeer.html @@ -79,13 +79,42 @@

Cla
Inheritance
-
NetPeer
+ + +
NetPeer
+
+

Namespace: LiteNetLib
Assembly: LiteNetLib.dll
Syntax
-
public class NetPeer
+
public class NetPeer : IPEndPoint

Fields

@@ -219,32 +248,6 @@
Property Value
- -

EndPoint

-

Peer ip address and port

-
-
-
Declaration
-
-
public IPEndPoint EndPoint { get; }
-
-
Property Value
- - - - - - - - - - - - - -
TypeDescription
IPEndPoint
- -

Mtu

Current MTU - Maximum Transfer Unit ( maximum udp packet size without fragmentation )

@@ -582,6 +585,33 @@
Parameters
+ +

GetHashCode()

+
+
+
Declaration
+
+
public override int GetHashCode()
+
+
Returns
+ + + + + + + + + + + + + +
TypeDescription
int
+
Overrides
+ + +

GetMaxSinglePacketSize(DeliveryMethod)

Gets maximum size of packet that will be not fragmented.

@@ -1448,6 +1478,35 @@
Exceptions
+ + +

Serialize()

+

IPEndPoint serialize

+
+
+
Declaration
+
+
public override SocketAddress Serialize()
+
+
Returns
+ + + + + + + + + + + + + +
TypeDescription
SocketAddress

SocketAddress

+
+
Overrides
+ +
diff --git a/docs/api/LiteNetLib.Utils.NetDataReader.html b/docs/api/LiteNetLib.Utils.NetDataReader.html index 57cf769e..75e15722 100644 --- a/docs/api/LiteNetLib.Utils.NetDataReader.html +++ b/docs/api/LiteNetLib.Utils.NetDataReader.html @@ -480,6 +480,416 @@
Declaration
+ +

Get(out bool)

+
+
+
Declaration
+
+
public void Get(out bool result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
boolresult
+ + + +

Get(out byte)

+
+
+
Declaration
+
+
public void Get(out byte result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
byteresult
+ + + +

Get(out char)

+
+
+
Declaration
+
+
public void Get(out char result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
charresult
+ + + +

Get(out double)

+
+
+
Declaration
+
+
public void Get(out double result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
doubleresult
+ + + +

Get(out short)

+
+
+
Declaration
+
+
public void Get(out short result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
shortresult
+ + + +

Get(out int)

+
+
+
Declaration
+
+
public void Get(out int result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
intresult
+ + + +

Get(out long)

+
+
+
Declaration
+
+
public void Get(out long result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
longresult
+ + + +

Get(out IPEndPoint)

+
+
+
Declaration
+
+
public void Get(out IPEndPoint result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
IPEndPointresult
+ + + +

Get(out sbyte)

+
+
+
Declaration
+
+
public void Get(out sbyte result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
sbyteresult
+ + + +

Get(out float)

+
+
+
Declaration
+
+
public void Get(out float result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
floatresult
+ + + +

Get(out string, int)

+
+
+
Declaration
+
+
public void Get(out string result, int maxLength)
+
+
Parameters
+ + + + + + + + + + + + + + + + + + + + +
TypeNameDescription
stringresult
intmaxLength
+ + + +

Get(out string)

+
+
+
Declaration
+
+
public void Get(out string result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
stringresult
+ + + +

Get(out ushort)

+
+
+
Declaration
+
+
public void Get(out ushort result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
ushortresult
+ + + +

Get(out uint)

+
+
+
Declaration
+
+
public void Get(out uint result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
uintresult
+ + + +

Get(out ulong)

+
+
+
Declaration
+
+
public void Get(out ulong result)
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
ulongresult
+ +

Get<T>()

@@ -520,6 +930,95 @@
Type Parameters
+ +

Get<T>(out T, Func<T>)

+
+
+
Declaration
+
+
public void Get<T>(out T result, Func<T> constructor) where T : class, INetSerializable
+
+
Parameters
+ + + + + + + + + + + + + + + + + + + + +
TypeNameDescription
Tresult
Func<T>constructor
+
Type Parameters
+ + + + + + + + + + + + + +
NameDescription
T
+ + + +

Get<T>(out T)

+
+
+
Declaration
+
+
public void Get<T>(out T result) where T : struct, INetSerializable
+
+
Parameters
+ + + + + + + + + + + + + + + +
TypeNameDescription
Tresult
+
Type Parameters
+ + + + + + + + + + + + + +
NameDescription
T
+ +

Get<T>(Func<T>)

@@ -1145,6 +1644,31 @@
Returns
+ +

GetRemainingBytesSpan()

+
+
+
Declaration
+
+
public ReadOnlySpan<byte> GetRemainingBytesSpan()
+
+
Returns
+ + + + + + + + + + + + + +
TypeDescription
ReadOnlySpan<byte>
+ +

GetSByte()

diff --git a/docs/api/LiteNetLib.Utils.PreserveAttribute.html b/docs/api/LiteNetLib.Utils.PreserveAttribute.html new file mode 100644 index 00000000..8a61f6c0 --- /dev/null +++ b/docs/api/LiteNetLib.Utils.PreserveAttribute.html @@ -0,0 +1,243 @@ + + + + + + + + Class PreserveAttribute + + + + + + + + + + + + + + + +
+
+ + + + +
+ + + +
+ + + + + + diff --git a/docs/api/LiteNetLib.Utils.html b/docs/api/LiteNetLib.Utils.html index f079835d..d7951740 100644 --- a/docs/api/LiteNetLib.Utils.html +++ b/docs/api/LiteNetLib.Utils.html @@ -95,6 +95,9 @@

NtpPacket

ParseException

+

PreserveAttribute

+

PreserveAttribute prevents byte code stripping from removing a class, method, field, or property.

+

Interfaces

INetSerializable

diff --git a/docs/api/toc.html b/docs/api/toc.html index ea4c7816..12210740 100644 --- a/docs/api/toc.html +++ b/docs/api/toc.html @@ -163,6 +163,9 @@
  • ParseException
  • +
  • + PreserveAttribute +
  • diff --git a/docs/manifest.json b/docs/manifest.json index 2a4a8307..a0c5141c 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1,6 +1,6 @@ { "homepages": [], - "source_base_path": "E:/Projects/LiteNetLib/docfx_project", + "source_base_path": "e:/Projects/LiteNetLib/docfx_project", "xrefmap": "xrefmap.yml", "files": [ { @@ -463,6 +463,16 @@ }, "version": "" }, + { + "type": "ManagedReference", + "source_relative_path": "api/LiteNetLib.Utils.PreserveAttribute.yml", + "output": { + ".html": { + "relative_path": "api/LiteNetLib.Utils.PreserveAttribute.html" + } + }, + "version": "" + }, { "type": "ManagedReference", "source_relative_path": "api/LiteNetLib.Utils.yml", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index 0212753f..c44a2db1 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -841,15 +841,15 @@ references: fullName.vb: LiteNetLib.Layers.Crc32cLayer.New nameWithType: Crc32cLayer.Crc32cLayer nameWithType.vb: Crc32cLayer.New -- uid: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - href: api/LiteNetLib.Layers.Crc32cLayer.html#LiteNetLib_Layers_Crc32cLayer_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__System_Int32__ - commentId: M:LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) - fullName: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int, ref int) - fullName.vb: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer, Integer) - nameWithType: Crc32cLayer.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - nameWithType.vb: Crc32cLayer.ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) +- uid: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + href: api/LiteNetLib.Layers.Crc32cLayer.html#LiteNetLib_Layers_Crc32cLayer_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__ + commentId: M:LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer) + fullName: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int) + fullName.vb: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer) + nameWithType: Crc32cLayer.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + nameWithType.vb: Crc32cLayer.ProcessInboundPacket(IPEndPoint, Byte(), Integer) - uid: LiteNetLib.Layers.Crc32cLayer.ProcessInboundPacket* name: ProcessInboundPacket href: api/LiteNetLib.Layers.Crc32cLayer.html#LiteNetLib_Layers_Crc32cLayer_ProcessInboundPacket_ @@ -904,15 +904,15 @@ references: commentId: F:LiteNetLib.Layers.PacketLayerBase.ExtraPacketSizeForLayer fullName: LiteNetLib.Layers.PacketLayerBase.ExtraPacketSizeForLayer nameWithType: PacketLayerBase.ExtraPacketSizeForLayer -- uid: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - href: api/LiteNetLib.Layers.PacketLayerBase.html#LiteNetLib_Layers_PacketLayerBase_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__System_Int32__ - commentId: M:LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) - fullName: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int, ref int) - fullName.vb: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer, Integer) - nameWithType: PacketLayerBase.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - nameWithType.vb: PacketLayerBase.ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) +- uid: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + href: api/LiteNetLib.Layers.PacketLayerBase.html#LiteNetLib_Layers_PacketLayerBase_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__ + commentId: M:LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer) + fullName: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int) + fullName.vb: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer) + nameWithType: PacketLayerBase.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + nameWithType.vb: PacketLayerBase.ProcessInboundPacket(IPEndPoint, Byte(), Integer) - uid: LiteNetLib.Layers.PacketLayerBase.ProcessInboundPacket* name: ProcessInboundPacket href: api/LiteNetLib.Layers.PacketLayerBase.html#LiteNetLib_Layers_PacketLayerBase_ProcessInboundPacket_ @@ -979,15 +979,15 @@ references: fullName.vb: LiteNetLib.Layers.XorEncryptLayer.New nameWithType: XorEncryptLayer.XorEncryptLayer nameWithType.vb: XorEncryptLayer.New -- uid: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - href: api/LiteNetLib.Layers.XorEncryptLayer.html#LiteNetLib_Layers_XorEncryptLayer_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__System_Int32__ - commentId: M:LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@,System.Int32@) - name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) - fullName: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int, ref int) - fullName.vb: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer, Integer) - nameWithType: XorEncryptLayer.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int, ref int) - nameWithType.vb: XorEncryptLayer.ProcessInboundPacket(IPEndPoint, Byte(), Integer, Integer) +- uid: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name: ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + href: api/LiteNetLib.Layers.XorEncryptLayer.html#LiteNetLib_Layers_XorEncryptLayer_ProcessInboundPacket_System_Net_IPEndPoint__System_Byte____System_Int32__ + commentId: M:LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint@,System.Byte[]@,System.Int32@) + name.vb: ProcessInboundPacket(IPEndPoint, Byte(), Integer) + fullName: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(ref System.Net.IPEndPoint, ref byte[], ref int) + fullName.vb: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket(System.Net.IPEndPoint, Byte(), Integer) + nameWithType: XorEncryptLayer.ProcessInboundPacket(ref IPEndPoint, ref byte[], ref int) + nameWithType.vb: XorEncryptLayer.ProcessInboundPacket(IPEndPoint, Byte(), Integer) - uid: LiteNetLib.Layers.XorEncryptLayer.ProcessInboundPacket* name: ProcessInboundPacket href: api/LiteNetLib.Layers.XorEncryptLayer.html#LiteNetLib_Layers_XorEncryptLayer_ProcessInboundPacket_ @@ -1520,6 +1520,12 @@ references: commentId: F:LiteNetLib.NetManager.DisconnectTimeout fullName: LiteNetLib.NetManager.DisconnectTimeout nameWithType: NetManager.DisconnectTimeout +- uid: LiteNetLib.NetManager.DontRoute + name: DontRoute + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_DontRoute + commentId: F:LiteNetLib.NetManager.DontRoute + fullName: LiteNetLib.NetManager.DontRoute + nameWithType: NetManager.DontRoute - uid: LiteNetLib.NetManager.EnableStatistics name: EnableStatistics href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_EnableStatistics @@ -1957,6 +1963,33 @@ references: fullName.vb: LiteNetLib.NetManager.SendToAll(Byte(), Integer, Integer, Byte, LiteNetLib.DeliveryMethod) nameWithType: NetManager.SendToAll(byte[], int, int, byte, DeliveryMethod) nameWithType.vb: NetManager.SendToAll(Byte(), Integer, Integer, Byte, DeliveryMethod) +- uid: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},LiteNetLib.DeliveryMethod,LiteNetLib.NetPeer) + name: SendToAll(ReadOnlySpan, DeliveryMethod, NetPeer) + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SendToAll_System_ReadOnlySpan_System_Byte__LiteNetLib_DeliveryMethod_LiteNetLib_NetPeer_ + commentId: M:LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},LiteNetLib.DeliveryMethod,LiteNetLib.NetPeer) + name.vb: SendToAll(ReadOnlySpan(Of Byte), DeliveryMethod, NetPeer) + fullName: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan, LiteNetLib.DeliveryMethod, LiteNetLib.NetPeer) + fullName.vb: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan(Of Byte), LiteNetLib.DeliveryMethod, LiteNetLib.NetPeer) + nameWithType: NetManager.SendToAll(ReadOnlySpan, DeliveryMethod, NetPeer) + nameWithType.vb: NetManager.SendToAll(ReadOnlySpan(Of Byte), DeliveryMethod, NetPeer) +- uid: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},LiteNetLib.DeliveryMethod) + name: SendToAll(ReadOnlySpan, DeliveryMethod) + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SendToAll_System_ReadOnlySpan_System_Byte__LiteNetLib_DeliveryMethod_ + commentId: M:LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},LiteNetLib.DeliveryMethod) + name.vb: SendToAll(ReadOnlySpan(Of Byte), DeliveryMethod) + fullName: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan, LiteNetLib.DeliveryMethod) + fullName.vb: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan(Of Byte), LiteNetLib.DeliveryMethod) + nameWithType: NetManager.SendToAll(ReadOnlySpan, DeliveryMethod) + nameWithType.vb: NetManager.SendToAll(ReadOnlySpan(Of Byte), DeliveryMethod) +- uid: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},System.Byte,LiteNetLib.DeliveryMethod,LiteNetLib.NetPeer) + name: SendToAll(ReadOnlySpan, byte, DeliveryMethod, NetPeer) + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SendToAll_System_ReadOnlySpan_System_Byte__System_Byte_LiteNetLib_DeliveryMethod_LiteNetLib_NetPeer_ + commentId: M:LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan{System.Byte},System.Byte,LiteNetLib.DeliveryMethod,LiteNetLib.NetPeer) + name.vb: SendToAll(ReadOnlySpan(Of Byte), Byte, DeliveryMethod, NetPeer) + fullName: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan, byte, LiteNetLib.DeliveryMethod, LiteNetLib.NetPeer) + fullName.vb: LiteNetLib.NetManager.SendToAll(System.ReadOnlySpan(Of Byte), Byte, LiteNetLib.DeliveryMethod, LiteNetLib.NetPeer) + nameWithType: NetManager.SendToAll(ReadOnlySpan, byte, DeliveryMethod, NetPeer) + nameWithType.vb: NetManager.SendToAll(ReadOnlySpan(Of Byte), Byte, DeliveryMethod, NetPeer) - uid: LiteNetLib.NetManager.SendToAll* name: SendToAll href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SendToAll_ @@ -2034,22 +2067,6 @@ references: commentId: F:LiteNetLib.NetManager.SimulationPacketLossChance fullName: LiteNetLib.NetManager.SimulationPacketLossChance nameWithType: NetManager.SimulationPacketLossChance -- uid: LiteNetLib.NetManager.SocketActive(System.Boolean) - name: SocketActive(bool) - href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SocketActive_System_Boolean_ - commentId: M:LiteNetLib.NetManager.SocketActive(System.Boolean) - name.vb: SocketActive(Boolean) - fullName: LiteNetLib.NetManager.SocketActive(bool) - fullName.vb: LiteNetLib.NetManager.SocketActive(Boolean) - nameWithType: NetManager.SocketActive(bool) - nameWithType.vb: NetManager.SocketActive(Boolean) -- uid: LiteNetLib.NetManager.SocketActive* - name: SocketActive - href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_SocketActive_ - commentId: Overload:LiteNetLib.NetManager.SocketActive - isSpec: "True" - fullName: LiteNetLib.NetManager.SocketActive - nameWithType: NetManager.SocketActive - uid: LiteNetLib.NetManager.Start name: Start() href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_Start @@ -2336,19 +2353,19 @@ references: isSpec: "True" fullName: LiteNetLib.NetPeer.Disconnect nameWithType: NetPeer.Disconnect -- uid: LiteNetLib.NetPeer.EndPoint - name: EndPoint - href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_EndPoint - commentId: P:LiteNetLib.NetPeer.EndPoint - fullName: LiteNetLib.NetPeer.EndPoint - nameWithType: NetPeer.EndPoint -- uid: LiteNetLib.NetPeer.EndPoint* - name: EndPoint - href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_EndPoint_ - commentId: Overload:LiteNetLib.NetPeer.EndPoint - isSpec: "True" - fullName: LiteNetLib.NetPeer.EndPoint - nameWithType: NetPeer.EndPoint +- uid: LiteNetLib.NetPeer.GetHashCode + name: GetHashCode() + href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_GetHashCode + commentId: M:LiteNetLib.NetPeer.GetHashCode + fullName: LiteNetLib.NetPeer.GetHashCode() + nameWithType: NetPeer.GetHashCode() +- uid: LiteNetLib.NetPeer.GetHashCode* + name: GetHashCode + href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_GetHashCode_ + commentId: Overload:LiteNetLib.NetPeer.GetHashCode + isSpec: "True" + fullName: LiteNetLib.NetPeer.GetHashCode + nameWithType: NetPeer.GetHashCode - uid: LiteNetLib.NetPeer.GetMaxSinglePacketSize(LiteNetLib.DeliveryMethod) name: GetMaxSinglePacketSize(DeliveryMethod) href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_GetMaxSinglePacketSize_LiteNetLib_DeliveryMethod_ @@ -2603,6 +2620,19 @@ references: isSpec: "True" fullName: LiteNetLib.NetPeer.SendWithDeliveryEvent nameWithType: NetPeer.SendWithDeliveryEvent +- uid: LiteNetLib.NetPeer.Serialize + name: Serialize() + href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_Serialize + commentId: M:LiteNetLib.NetPeer.Serialize + fullName: LiteNetLib.NetPeer.Serialize() + nameWithType: NetPeer.Serialize() +- uid: LiteNetLib.NetPeer.Serialize* + name: Serialize + href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_Serialize_ + commentId: Overload:LiteNetLib.NetPeer.Serialize + isSpec: "True" + fullName: LiteNetLib.NetPeer.Serialize + nameWithType: NetPeer.Serialize - uid: LiteNetLib.NetPeer.Statistics name: Statistics href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_Statistics @@ -3203,6 +3233,141 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.EndOfData nameWithType: NetDataReader.EndOfData +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Boolean@) + name: Get(out bool) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Boolean__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Boolean@) + name.vb: Get(Boolean) + fullName: LiteNetLib.Utils.NetDataReader.Get(out bool) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Boolean) + nameWithType: NetDataReader.Get(out bool) + nameWithType.vb: NetDataReader.Get(Boolean) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Byte@) + name: Get(out byte) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Byte__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Byte@) + name.vb: Get(Byte) + fullName: LiteNetLib.Utils.NetDataReader.Get(out byte) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Byte) + nameWithType: NetDataReader.Get(out byte) + nameWithType.vb: NetDataReader.Get(Byte) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Char@) + name: Get(out char) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Char__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Char@) + name.vb: Get(Char) + fullName: LiteNetLib.Utils.NetDataReader.Get(out char) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Char) + nameWithType: NetDataReader.Get(out char) + nameWithType.vb: NetDataReader.Get(Char) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Double@) + name: Get(out double) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Double__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Double@) + name.vb: Get(Double) + fullName: LiteNetLib.Utils.NetDataReader.Get(out double) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Double) + nameWithType: NetDataReader.Get(out double) + nameWithType.vb: NetDataReader.Get(Double) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Int16@) + name: Get(out short) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Int16__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Int16@) + name.vb: Get(Short) + fullName: LiteNetLib.Utils.NetDataReader.Get(out short) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Short) + nameWithType: NetDataReader.Get(out short) + nameWithType.vb: NetDataReader.Get(Short) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Int32@) + name: Get(out int) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Int32__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Int32@) + name.vb: Get(Integer) + fullName: LiteNetLib.Utils.NetDataReader.Get(out int) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Integer) + nameWithType: NetDataReader.Get(out int) + nameWithType.vb: NetDataReader.Get(Integer) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Int64@) + name: Get(out long) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Int64__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Int64@) + name.vb: Get(Long) + fullName: LiteNetLib.Utils.NetDataReader.Get(out long) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Long) + nameWithType: NetDataReader.Get(out long) + nameWithType.vb: NetDataReader.Get(Long) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Net.IPEndPoint@) + name: Get(out IPEndPoint) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Net_IPEndPoint__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Net.IPEndPoint@) + name.vb: Get(IPEndPoint) + fullName: LiteNetLib.Utils.NetDataReader.Get(out System.Net.IPEndPoint) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(System.Net.IPEndPoint) + nameWithType: NetDataReader.Get(out IPEndPoint) + nameWithType.vb: NetDataReader.Get(IPEndPoint) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.SByte@) + name: Get(out sbyte) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_SByte__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.SByte@) + name.vb: Get(SByte) + fullName: LiteNetLib.Utils.NetDataReader.Get(out sbyte) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(SByte) + nameWithType: NetDataReader.Get(out sbyte) + nameWithType.vb: NetDataReader.Get(SByte) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.Single@) + name: Get(out float) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_Single__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.Single@) + name.vb: Get(Single) + fullName: LiteNetLib.Utils.NetDataReader.Get(out float) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Single) + nameWithType: NetDataReader.Get(out float) + nameWithType.vb: NetDataReader.Get(Single) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.String@,System.Int32) + name: Get(out string, int) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_String__System_Int32_ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.String@,System.Int32) + name.vb: Get(String, Integer) + fullName: LiteNetLib.Utils.NetDataReader.Get(out string, int) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(String, Integer) + nameWithType: NetDataReader.Get(out string, int) + nameWithType.vb: NetDataReader.Get(String, Integer) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.String@) + name: Get(out string) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_String__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.String@) + name.vb: Get(String) + fullName: LiteNetLib.Utils.NetDataReader.Get(out string) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(String) + nameWithType: NetDataReader.Get(out string) + nameWithType.vb: NetDataReader.Get(String) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.UInt16@) + name: Get(out ushort) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_UInt16__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.UInt16@) + name.vb: Get(UShort) + fullName: LiteNetLib.Utils.NetDataReader.Get(out ushort) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(UShort) + nameWithType: NetDataReader.Get(out ushort) + nameWithType.vb: NetDataReader.Get(UShort) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.UInt32@) + name: Get(out uint) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_UInt32__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.UInt32@) + name.vb: Get(UInteger) + fullName: LiteNetLib.Utils.NetDataReader.Get(out uint) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(UInteger) + nameWithType: NetDataReader.Get(out uint) + nameWithType.vb: NetDataReader.Get(UInteger) +- uid: LiteNetLib.Utils.NetDataReader.Get(System.UInt64@) + name: Get(out ulong) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_System_UInt64__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get(System.UInt64@) + name.vb: Get(ULong) + fullName: LiteNetLib.Utils.NetDataReader.Get(out ulong) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(ULong) + nameWithType: NetDataReader.Get(out ulong) + nameWithType.vb: NetDataReader.Get(ULong) - uid: LiteNetLib.Utils.NetDataReader.Get* name: Get href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get_ @@ -3219,6 +3384,24 @@ references: fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Of T)() nameWithType: NetDataReader.Get() nameWithType.vb: NetDataReader.Get(Of T)() +- uid: LiteNetLib.Utils.NetDataReader.Get``1(``0@,System.Func{``0}) + name: Get(out T, Func) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get__1___0__System_Func___0__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get``1(``0@,System.Func{``0}) + name.vb: Get(Of T)(T, Func(Of T)) + fullName: LiteNetLib.Utils.NetDataReader.Get(out T, System.Func) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Of T)(T, System.Func(Of T)) + nameWithType: NetDataReader.Get(out T, Func) + nameWithType.vb: NetDataReader.Get(Of T)(T, Func(Of T)) +- uid: LiteNetLib.Utils.NetDataReader.Get``1(``0@) + name: Get(out T) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get__1___0__ + commentId: M:LiteNetLib.Utils.NetDataReader.Get``1(``0@) + name.vb: Get(Of T)(T) + fullName: LiteNetLib.Utils.NetDataReader.Get(out T) + fullName.vb: LiteNetLib.Utils.NetDataReader.Get(Of T)(T) + nameWithType: NetDataReader.Get(out T) + nameWithType.vb: NetDataReader.Get(Of T)(T) - uid: LiteNetLib.Utils.NetDataReader.Get``1(System.Func{``0}) name: Get(Func) href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get__1_System_Func___0__ @@ -3493,6 +3676,19 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.GetRemainingBytesSegment nameWithType: NetDataReader.GetRemainingBytesSegment +- uid: LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan + name: GetRemainingBytesSpan() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetRemainingBytesSpan + commentId: M:LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan + fullName: LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan() + nameWithType: NetDataReader.GetRemainingBytesSpan() +- uid: LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan* + name: GetRemainingBytesSpan + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetRemainingBytesSpan_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.GetRemainingBytesSpan + nameWithType: NetDataReader.GetRemainingBytesSpan - uid: LiteNetLib.Utils.NetDataReader.GetSByte name: GetSByte() href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetSByte @@ -5554,3 +5750,9 @@ references: fullName.vb: LiteNetLib.Utils.ParseException.New nameWithType: ParseException.ParseException nameWithType.vb: ParseException.New +- uid: LiteNetLib.Utils.PreserveAttribute + name: PreserveAttribute + href: api/LiteNetLib.Utils.PreserveAttribute.html + commentId: T:LiteNetLib.Utils.PreserveAttribute + fullName: LiteNetLib.Utils.PreserveAttribute + nameWithType: PreserveAttribute From 3fee090c4681b7674fc760e45f30b75dfc51e62d Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 11:07:55 +0200 Subject: [PATCH 003/200] update unity example --- LiteNetLib/NetPeer.cs | 2 +- LiteNetLibSampleUnity/Assets/GameClient.cs | 22 +- LiteNetLibSampleUnity/Assets/GameServer.cs | 28 +- LiteNetLibSampleUnity/Assets/Resources.meta | 8 + .../Assets/Resources/BillingMode.json | 1 + .../Assets/Resources/BillingMode.json.meta | 7 + .../ProjectSettings/MemorySettings.asset | 35 + .../PackageManagerSettings.asset | 36 + .../ProjectSettings/PresetManager.asset | Bin 4104 -> 146 bytes .../ProjectSettings/ProjectSettings.asset | 606 +++-- .../ProjectSettings/ProjectVersion.txt | 3 +- .../ProjectSettings/VFXManager.asset | Bin 4148 -> 465 bytes .../VersionControlSettings.asset | 8 + .../UserSettings/EditorUserSettings.asset | 28 + .../Layouts/CurrentMaximizeLayout.dwlt | 1680 +++++++++++++ .../UserSettings/Layouts/default-2022.dwlt | 2095 +++++++++++++++++ .../UserSettings/Search.settings | 1 + 17 files changed, 4355 insertions(+), 205 deletions(-) create mode 100644 LiteNetLibSampleUnity/Assets/Resources.meta create mode 100644 LiteNetLibSampleUnity/Assets/Resources/BillingMode.json create mode 100644 LiteNetLibSampleUnity/Assets/Resources/BillingMode.json.meta create mode 100644 LiteNetLibSampleUnity/ProjectSettings/MemorySettings.asset create mode 100644 LiteNetLibSampleUnity/ProjectSettings/PackageManagerSettings.asset create mode 100644 LiteNetLibSampleUnity/ProjectSettings/VersionControlSettings.asset create mode 100644 LiteNetLibSampleUnity/UserSettings/EditorUserSettings.asset create mode 100644 LiteNetLibSampleUnity/UserSettings/Layouts/CurrentMaximizeLayout.dwlt create mode 100644 LiteNetLibSampleUnity/UserSettings/Layouts/default-2022.dwlt create mode 100644 LiteNetLibSampleUnity/UserSettings/Search.settings diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index 4d7a2b56..38c10999 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -257,7 +257,7 @@ internal void FinishEndPointChange(IPEndPoint newEndPoint) if (_connectionState != ConnectionState.EndPointChange) return; _connectionState = ConnectionState.Connected; - + Address = newEndPoint.Address; Port = newEndPoint.Port; diff --git a/LiteNetLibSampleUnity/Assets/GameClient.cs b/LiteNetLibSampleUnity/Assets/GameClient.cs index 18fff780..f6a120e9 100644 --- a/LiteNetLibSampleUnity/Assets/GameClient.cs +++ b/LiteNetLibSampleUnity/Assets/GameClient.cs @@ -14,7 +14,7 @@ public class GameClient : MonoBehaviour, INetEventListener private float _oldBallPosX; private float _lerpTime; - void Start() + private void Start() { _netClient = new NetManager(this); _netClient.UnconnectedMessagesEnabled = true; @@ -22,7 +22,7 @@ void Start() _netClient.Start(); } - void Update() + private void Update() { _netClient.PollEvents(); @@ -43,23 +43,23 @@ void Update() } } - void OnDestroy() + private void OnDestroy() { if (_netClient != null) _netClient.Stop(); } - public void OnPeerConnected(NetPeer peer) + void INetEventListener.OnPeerConnected(NetPeer peer) { - Debug.Log("[CLIENT] We connected to " + peer.EndPoint); + Debug.Log("[CLIENT] We connected to " + peer); } - public void OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) + void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) { Debug.Log("[CLIENT] We received error " + socketErrorCode); } - public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod) + void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod) { _newBallPosX = reader.GetFloat(); @@ -73,7 +73,7 @@ public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMetho _lerpTime = 0f; } - public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) + void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { if (messageType == UnconnectedMessageType.BasicMessage && _netClient.ConnectedPeersCount == 0 && reader.GetInt() == 1) { @@ -82,17 +82,17 @@ public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketRead } } - public void OnNetworkLatencyUpdate(NetPeer peer, int latency) + void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) { } - public void OnConnectionRequest(ConnectionRequest request) + void INetEventListener.OnConnectionRequest(ConnectionRequest request) { } - public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) + void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { Debug.Log("[CLIENT] We disconnected because " + disconnectInfo.Reason); } diff --git a/LiteNetLibSampleUnity/Assets/GameServer.cs b/LiteNetLibSampleUnity/Assets/GameServer.cs index 3e06ee57..0f5641ee 100644 --- a/LiteNetLibSampleUnity/Assets/GameServer.cs +++ b/LiteNetLibSampleUnity/Assets/GameServer.cs @@ -13,7 +13,7 @@ public class GameServer : MonoBehaviour, INetEventListener, INetLogger [SerializeField] private GameObject _serverBall; - void Start() + private void Start() { NetDebug.Logger = this; _dataWriter = new NetDataWriter(); @@ -23,12 +23,12 @@ void Start() _netServer.UpdateTime = 15; } - void Update() + private void Update() { _netServer.PollEvents(); } - void FixedUpdate() + private void FixedUpdate() { if (_ourPeer != null) { @@ -39,25 +39,25 @@ void FixedUpdate() } } - void OnDestroy() + private void OnDestroy() { NetDebug.Logger = null; if (_netServer != null) _netServer.Stop(); } - public void OnPeerConnected(NetPeer peer) + void INetEventListener.OnPeerConnected(NetPeer peer) { - Debug.Log("[SERVER] We have new peer " + peer.EndPoint); + Debug.Log("[SERVER] We have new peer " + peer); _ourPeer = peer; } - public void OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) + void INetEventListener.OnNetworkError(IPEndPoint endPoint, SocketError socketErrorCode) { Debug.Log("[SERVER] error " + socketErrorCode); } - public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, + void INetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType) { if (messageType == UnconnectedMessageType.Broadcast) @@ -69,27 +69,27 @@ public void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketRead } } - public void OnNetworkLatencyUpdate(NetPeer peer, int latency) + void INetEventListener.OnNetworkLatencyUpdate(NetPeer peer, int latency) { } - public void OnConnectionRequest(ConnectionRequest request) + void INetEventListener.OnConnectionRequest(ConnectionRequest request) { request.AcceptIfKey("sample_app"); } - public void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) + void INetEventListener.OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo) { - Debug.Log("[SERVER] peer disconnected " + peer.EndPoint + ", info: " + disconnectInfo.Reason); + Debug.Log("[SERVER] peer disconnected " + peer + ", info: " + disconnectInfo.Reason); if (peer == _ourPeer) _ourPeer = null; } - public void OnNetworkReceive(NetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod) + void INetEventListener.OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channelNumber, DeliveryMethod deliveryMethod) { } - public void WriteNet(NetLogLevel level, string str, params object[] args) + void INetLogger.WriteNet(NetLogLevel level, string str, params object[] args) { Debug.LogFormat(str, args); } diff --git a/LiteNetLibSampleUnity/Assets/Resources.meta b/LiteNetLibSampleUnity/Assets/Resources.meta new file mode 100644 index 00000000..0ec2b74a --- /dev/null +++ b/LiteNetLibSampleUnity/Assets/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0680635b8862cad41957568e3143c8c7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json b/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json new file mode 100644 index 00000000..6f4bfb71 --- /dev/null +++ b/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json @@ -0,0 +1 @@ +{"androidStore":"GooglePlay"} \ No newline at end of file diff --git a/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json.meta b/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json.meta new file mode 100644 index 00000000..19a785dd --- /dev/null +++ b/LiteNetLibSampleUnity/Assets/Resources/BillingMode.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 935f8151a9a85ee40bfcd6cbe0333137 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/LiteNetLibSampleUnity/ProjectSettings/MemorySettings.asset b/LiteNetLibSampleUnity/ProjectSettings/MemorySettings.asset new file mode 100644 index 00000000..5b5facec --- /dev/null +++ b/LiteNetLibSampleUnity/ProjectSettings/MemorySettings.asset @@ -0,0 +1,35 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!387306366 &1 +MemorySettings: + m_ObjectHideFlags: 0 + m_EditorMemorySettings: + m_MainAllocatorBlockSize: -1 + m_ThreadAllocatorBlockSize: -1 + m_MainGfxBlockSize: -1 + m_ThreadGfxBlockSize: -1 + m_CacheBlockSize: -1 + m_TypetreeBlockSize: -1 + m_ProfilerBlockSize: -1 + m_ProfilerEditorBlockSize: -1 + m_BucketAllocatorGranularity: -1 + m_BucketAllocatorBucketsCount: -1 + m_BucketAllocatorBlockSize: -1 + m_BucketAllocatorBlockCount: -1 + m_ProfilerBucketAllocatorGranularity: -1 + m_ProfilerBucketAllocatorBucketsCount: -1 + m_ProfilerBucketAllocatorBlockSize: -1 + m_ProfilerBucketAllocatorBlockCount: -1 + m_TempAllocatorSizeMain: -1 + m_JobTempAllocatorBlockSize: -1 + m_BackgroundJobTempAllocatorBlockSize: -1 + m_JobTempAllocatorReducedBlockSize: -1 + m_TempAllocatorSizeGIBakingWorker: -1 + m_TempAllocatorSizeNavMeshWorker: -1 + m_TempAllocatorSizeAudioWorker: -1 + m_TempAllocatorSizeCloudWorker: -1 + m_TempAllocatorSizeGfx: -1 + m_TempAllocatorSizeJobWorker: -1 + m_TempAllocatorSizeBackgroundWorker: -1 + m_TempAllocatorSizePreloadManager: -1 + m_PlatformMemorySettings: {} diff --git a/LiteNetLibSampleUnity/ProjectSettings/PackageManagerSettings.asset b/LiteNetLibSampleUnity/ProjectSettings/PackageManagerSettings.asset new file mode 100644 index 00000000..89ffc0e9 --- /dev/null +++ b/LiteNetLibSampleUnity/ProjectSettings/PackageManagerSettings.asset @@ -0,0 +1,36 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 53 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 13964, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_EnablePreReleasePackages: 0 + m_AdvancedSettingsExpanded: 1 + m_ScopedRegistriesSettingsExpanded: 1 + m_SeeAllPackageVersions: 0 + m_DismissPreviewPackagesInUse: 0 + oneTimeWarningShown: 0 + m_Registries: + - m_Id: main + m_Name: + m_Url: https://packages.unity.com + m_Scopes: [] + m_IsDefault: 1 + m_Capabilities: 7 + m_ConfigSource: 0 + m_UserSelectedRegistryName: + m_UserAddingNewScopedRegistry: 0 + m_RegistryInfoDraft: + m_Modified: 0 + m_ErrorMessage: + m_UserModificationsInstanceId: -864 + m_OriginalInstanceId: -866 + m_LoadAssets: 0 diff --git a/LiteNetLibSampleUnity/ProjectSettings/PresetManager.asset b/LiteNetLibSampleUnity/ProjectSettings/PresetManager.asset index 3f07844c98aef18697edd42325705d4236b5c069..67a94daefe2e6bce3ec73546ad7cda94f702ad22 100644 GIT binary patch literal 146 zcmY$5boBL6Fw`^TQVnr*S5PcfR47SIw<^ucEU7e3(M!(H)iE+KG_>N<)zt;b8X8-e znOGW{nOiET8FB>_r52}__$KBhrl%HJaVaR|#``B_r6!knWTvFL* mG81z$t5Q?KQj3Z+^Yg3}jKHd0QqvMkb4noQ02No)asdFNTr08w literal 4104 zcmeH_yGlbr5Qb-S^?uhzL41K|EWCgOix3nqM6nM?J(_4DYL0@1u$@n!txZT}qgYwl zSzFlpC?5ZR_e6|uAnd@LnfZ2hcK1(2;!`369U?M_h#)dMlU>NnX66pE@)d@mQeczQ zjcp0TZ_~HjX`GHUjA{qUr$fS;k}x!s8N+*I4Uc!pZ${B+y9 zddZEaWeYp`F4ok^@`Tat1~upRBS!CPn{R%|W$v-}Z|OG3ei->3BIoliLxeEir-Aqg zCm)8>6kbXFTRMywrVanC!)U~d=YHJ}HoOz>&_9=2DeoV67u8_BQV%4`ZHpl`-MKpT zCE%x4+Vq0TrBAY&M`;J`vo00`4lGovcB$wE<-a`zuUg&p_Ks!W9&6{<+fNowTCz(y qOtcwZWGo6MZ~YnUiu*bRoB~b(r+`zyDc}@v3OEIv0#1Sdt-v=11*1d& diff --git a/LiteNetLibSampleUnity/ProjectSettings/ProjectSettings.asset b/LiteNetLibSampleUnity/ProjectSettings/ProjectSettings.asset index 85038959..29e4475c 100644 --- a/LiteNetLibSampleUnity/ProjectSettings/ProjectSettings.asset +++ b/LiteNetLibSampleUnity/ProjectSettings/ProjectSettings.asset @@ -3,9 +3,11 @@ --- !u!129 &1 PlayerSettings: m_ObjectHideFlags: 0 - serializedVersion: 11 + serializedVersion: 26 productGUID: cf592f4b245d2b540a06dd6461f51365 AndroidProfiler: 0 + AndroidFilterTouchesWhenObscured: 0 + AndroidEnableSustainedPerformanceMode: 0 defaultScreenOrientation: 4 targetDevice: 2 useOnDemandResources: 0 @@ -14,7 +16,7 @@ PlayerSettings: productName: LiteNetLibSampleUnity defaultCursor: {fileID: 0} cursorHotspot: {x: 0, y: 0} - m_SplashScreenBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21176471, a: 1} + m_SplashScreenBackgroundColor: {r: 0.12156863, g: 0.12156863, b: 0.1254902, a: 1} m_ShowUnitySplashScreen: 1 m_ShowUnitySplashLogo: 1 m_SplashScreenOverlayOpacity: 1 @@ -38,8 +40,6 @@ PlayerSettings: width: 1 height: 1 m_SplashScreenLogos: [] - m_SplashScreenBackgroundLandscape: {fileID: 0} - m_SplashScreenBackgroundPortrait: {fileID: 0} m_VirtualRealitySplashScreen: {fileID: 0} m_HolographicTrackingLossScreen: {fileID: 0} defaultScreenWidth: 1024 @@ -48,37 +48,53 @@ PlayerSettings: defaultScreenHeightWeb: 600 m_StereoRenderingPath: 0 m_ActiveColorSpace: 0 + unsupportedMSAAFallback: 0 + m_SpriteBatchVertexThreshold: 300 m_MTRendering: 1 - m_MobileMTRendering: 0 + mipStripping: 0 + numberOfMipsStripped: 0 + numberOfMipsStrippedPerMipmapLimitGroup: {} m_StackTraceTypes: 010000000100000001000000010000000100000001000000 iosShowActivityIndicatorOnLoading: -1 androidShowActivityIndicatorOnLoading: -1 - tizenShowActivityIndicatorOnLoading: -1 - iosAppInBackgroundBehavior: 0 - displayResolutionDialog: 1 - iosAllowHTTPDownload: 1 + iosUseCustomAppBackgroundBehavior: 0 allowedAutorotateToPortrait: 1 allowedAutorotateToPortraitUpsideDown: 1 allowedAutorotateToLandscapeRight: 1 allowedAutorotateToLandscapeLeft: 1 useOSAutorotation: 1 use32BitDisplayBuffer: 1 + preserveFramebufferAlpha: 0 disableDepthAndStencilBuffers: 0 - defaultIsFullScreen: 1 + androidStartInFullscreen: 1 + androidRenderOutsideSafeArea: 1 + androidUseSwappy: 0 + androidBlitType: 0 + androidResizableWindow: 0 + androidDefaultWindowWidth: 1920 + androidDefaultWindowHeight: 1080 + androidMinimumWindowWidth: 400 + androidMinimumWindowHeight: 300 + androidFullscreenMode: 1 defaultIsNativeResolution: 1 + macRetinaSupport: 1 runInBackground: 0 captureSingleScreen: 0 muteOtherAudioSources: 0 Prepare IOS For Recording: 0 + Force IOS Speakers When Recording: 0 + deferSystemGesturesMode: 0 + hideHomeButton: 0 submitAnalytics: 1 usePlayerLog: 1 + dedicatedServerOptimizations: 0 bakeCollisionMeshes: 0 forceSingleInstance: 0 + useFlipModelSwapchain: 1 resizableWindow: 0 useMacAppStoreValidation: 0 macAppStoreCategory: public.app-category.games gpuSkinning: 0 - graphicsJobs: 0 xboxPIXTextureCapture: 0 xboxEnableAvatar: 0 xboxEnableKinect: 0 @@ -86,66 +102,75 @@ PlayerSettings: xboxEnableFitness: 0 visibleInBackground: 0 allowFullscreenSwitch: 1 - graphicsJobMode: 0 - macFullscreenMode: 2 - d3d9FullscreenMode: 1 - d3d11FullscreenMode: 1 + fullscreenMode: 1 xboxSpeechDB: 0 xboxEnableHeadOrientation: 0 xboxEnableGuest: 0 xboxEnablePIXSampling: 0 - n3dsDisableStereoscopicView: 0 - n3dsEnableSharedListOpt: 1 - n3dsEnableVSync: 0 - ignoreAlphaClear: 0 + metalFramebufferOnly: 0 xboxOneResolution: 0 + xboxOneSResolution: 0 + xboxOneXResolution: 3 xboxOneMonoLoggingLevel: 0 xboxOneLoggingLevel: 1 - videoMemoryForVertexBuffers: 0 - psp2PowerMode: 0 - psp2AcquireBGM: 1 - wiiUTVResolution: 0 - wiiUGamePadMSAA: 1 - wiiUSupportsNunchuk: 0 - wiiUSupportsClassicController: 0 - wiiUSupportsBalanceBoard: 0 - wiiUSupportsMotionPlus: 0 - wiiUSupportsProController: 0 - wiiUAllowScreenCapture: 1 - wiiUControllerCount: 0 - m_SupportedAspectRatios: - 4:3: 1 - 5:4: 1 - 16:10: 1 - 16:9: 1 - Others: 1 + xboxOneDisableEsram: 0 + xboxOneEnableTypeOptimization: 0 + xboxOnePresentImmediateThreshold: 0 + switchQueueCommandMemory: 1048576 + switchQueueControlMemory: 16384 + switchQueueComputeMemory: 262144 + switchNVNShaderPoolsGranularity: 33554432 + switchNVNDefaultPoolsGranularity: 16777216 + switchNVNOtherPoolsGranularity: 16777216 + switchGpuScratchPoolGranularity: 2097152 + switchAllowGpuScratchShrinking: 0 + switchNVNMaxPublicTextureIDCount: 0 + switchNVNMaxPublicSamplerIDCount: 0 + switchNVNGraphicsFirmwareMemory: 32 + switchMaxWorkerMultiple: 8 + stadiaPresentMode: 0 + stadiaTargetFramerate: 0 + vulkanNumSwapchainBuffers: 3 + vulkanEnableSetSRGBWrite: 0 + vulkanEnablePreTransform: 0 + vulkanEnableLateAcquireNextImage: 0 + vulkanEnableCommandBufferRecycling: 1 + loadStoreDebugModeEnabled: 0 bundleVersion: 1.0 preloadedAssets: [] metroInputSource: 0 + wsaTransparentSwapchain: 0 m_HolographicPauseOnTrackingLoss: 1 xboxOneDisableKinectGpuReservation: 0 xboxOneEnable7thCore: 0 vrSettings: - cardboard: - depthFormat: 0 - enableTransitionView: 0 - daydream: - depthFormat: 0 - useSustainedPerformanceMode: 0 - hololens: - depthFormat: 1 - protectGraphicsMemory: 0 + enable360StereoCapture: 0 + isWsaHolographicRemotingEnabled: 0 + enableFrameTimingStats: 0 + enableOpenGLProfilerGPURecorders: 1 + allowHDRDisplaySupport: 0 useHDRDisplay: 0 + hdrBitDepth: 0 + m_ColorGamuts: 00000000 + targetPixelDensity: 30 + resolutionScalingMode: 0 + resetResolutionOnWindowResize: 0 + androidSupportedAspectRatio: 1 + androidMaxAspectRatio: 2.1 applicationIdentifier: Android: com.RevenantX.LiteNetLibTest Standalone: unity.RevenantX.LiteNetLibSampleUnity Tizen: com.RevenantX.LiteNetLibTest - iOS: com.RevenantX.LiteNetLibTest + iPhone: com.RevenantX.LiteNetLibTest tvOS: com.RevenantX.LiteNetLibTest buildNumber: - iOS: 0 + Standalone: 0 + VisionOS: 0 + iPhone: 0 + tvOS: 0 + overrideDefaultApplicationIdentifier: 1 AndroidBundleVersionCode: 1 - AndroidMinSdkVersion: 16 + AndroidMinSdkVersion: 22 AndroidTargetSdkVersion: 0 AndroidPreferredInstallLocation: 1 aotOptions: @@ -158,35 +183,31 @@ PlayerSettings: APKExpansionFiles: 0 keepLoadedShadersAlive: 0 StripUnusedMeshComponents: 0 - VertexChannelCompressionMask: - serializedVersion: 2 - m_Bits: 238 + strictShaderVariantMatching: 0 + VertexChannelCompressionMask: 214 iPhoneSdkVersion: 988 - iOSTargetOSVersionString: 6.0 + iOSTargetOSVersionString: 12.0 tvOSSdkVersion: 0 tvOSRequireExtendedGameController: 0 - tvOSTargetOSVersionString: 9.0 + tvOSTargetOSVersionString: 12.0 + VisionOSSdkVersion: 0 + VisionOSTargetOSVersionString: 1.0 uIPrerenderedIcon: 0 uIRequiresPersistentWiFi: 0 uIRequiresFullScreen: 1 uIStatusBarHidden: 1 uIExitOnSuspend: 0 uIStatusBarStyle: 0 - iPhoneSplashScreen: {fileID: 0} - iPhoneHighResSplashScreen: {fileID: 0} - iPhoneTallHighResSplashScreen: {fileID: 0} - iPhone47inSplashScreen: {fileID: 0} - iPhone55inPortraitSplashScreen: {fileID: 0} - iPhone55inLandscapeSplashScreen: {fileID: 0} - iPadPortraitSplashScreen: {fileID: 0} - iPadHighResPortraitSplashScreen: {fileID: 0} - iPadLandscapeSplashScreen: {fileID: 0} - iPadHighResLandscapeSplashScreen: {fileID: 0} appleTVSplashScreen: {fileID: 0} + appleTVSplashScreen2x: {fileID: 0} tvOSSmallIconLayers: [] + tvOSSmallIconLayers2x: [] tvOSLargeIconLayers: [] + tvOSLargeIconLayers2x: [] tvOSTopShelfImageLayers: [] + tvOSTopShelfImageLayers2x: [] tvOSTopShelfImageWideLayers: [] + tvOSTopShelfImageWideLayers2x: [] iOSLaunchScreenType: 0 iOSLaunchScreenPortrait: {fileID: 0} iOSLaunchScreenLandscape: {fileID: 0} @@ -204,31 +225,64 @@ PlayerSettings: iOSLaunchScreeniPadFillPct: 100 iOSLaunchScreeniPadSize: 100 iOSLaunchScreeniPadCustomXibPath: + iOSLaunchScreenCustomStoryboardPath: + iOSLaunchScreeniPadCustomStoryboardPath: iOSDeviceRequirements: [] iOSURLSchemes: [] + macOSURLSchemes: [] iOSBackgroundModes: 0 iOSMetalForceHardShadows: 0 metalEditorSupport: 1 metalAPIValidation: 1 iOSRenderExtraFrameOnPause: 1 + iosCopyPluginsCodeInsteadOfSymlink: 0 appleDeveloperTeamID: iOSManualSigningProvisioningProfileID: tvOSManualSigningProvisioningProfileID: + VisionOSManualSigningProvisioningProfileID: + iOSManualSigningProvisioningProfileType: 0 + tvOSManualSigningProvisioningProfileType: 0 + VisionOSManualSigningProvisioningProfileType: 0 appleEnableAutomaticSigning: 0 - AndroidTargetDevice: 0 + iOSRequireARKit: 0 + iOSAutomaticallyDetectAndAddCapabilities: 1 + appleEnableProMotion: 0 + shaderPrecisionModel: 0 + clonedFromGUID: 00000000000000000000000000000000 + templatePackageId: + templateDefaultScene: + useCustomMainManifest: 0 + useCustomLauncherManifest: 0 + useCustomMainGradleTemplate: 0 + useCustomLauncherGradleManifest: 0 + useCustomBaseGradleTemplate: 0 + useCustomGradlePropertiesTemplate: 0 + useCustomGradleSettingsTemplate: 0 + useCustomProguardFile: 0 + AndroidTargetArchitectures: 1 + AndroidTargetDevices: 0 AndroidSplashScreenScale: 0 androidSplashScreen: {fileID: 0} - AndroidKeystoreName: + AndroidKeystoreName: '{inproject}: ' AndroidKeyaliasName: + AndroidEnableArmv9SecurityFeatures: 0 + AndroidBuildApkPerCpuArchitecture: 0 AndroidTVCompatibility: 1 AndroidIsGame: 1 + AndroidEnableTango: 0 androidEnableBanner: 1 + androidUseLowAccuracyLocation: 0 + androidUseCustomKeystore: 0 m_AndroidBanners: - width: 320 height: 180 banner: {fileID: 0} androidGamepadSupportLevel: 0 - resolutionDialogBanner: {fileID: 0} + chromeosInputEmulation: 1 + AndroidMinifyRelease: 0 + AndroidMinifyDebug: 0 + AndroidValidateAppBundleSize: 1 + AndroidAppBundleSizeToValidate: 150 m_BuildTargetIcons: - m_BuildTarget: m_Icons: @@ -236,14 +290,159 @@ PlayerSettings: m_Icon: {fileID: 0} m_Width: 128 m_Height: 128 + m_Kind: 0 + m_BuildTargetPlatformIcons: + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: m_BuildTargetBatching: [] - m_BuildTargetGraphicsAPIs: [] + m_BuildTargetShaderSettings: [] + m_BuildTargetGraphicsJobs: + - m_BuildTarget: WindowsStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: MacStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: LinuxStandaloneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AndroidPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: iOSSupport + m_GraphicsJobs: 0 + - m_BuildTarget: PS4Player + m_GraphicsJobs: 0 + - m_BuildTarget: PS5Player + m_GraphicsJobs: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobs: 0 + - m_BuildTarget: GameCoreXboxOneSupport + m_GraphicsJobs: 0 + - m_BuildTarget: GameCoreScarlettSupport + m_GraphicsJobs: 0 + - m_BuildTarget: Switch + m_GraphicsJobs: 0 + - m_BuildTarget: WebGLSupport + m_GraphicsJobs: 0 + - m_BuildTarget: MetroSupport + m_GraphicsJobs: 0 + - m_BuildTarget: AppleTVSupport + m_GraphicsJobs: 0 + - m_BuildTarget: VisionOSPlayer + m_GraphicsJobs: 0 + - m_BuildTarget: BJMSupport + m_GraphicsJobs: 0 + - m_BuildTarget: CloudRendering + m_GraphicsJobs: 0 + - m_BuildTarget: EmbeddedLinux + m_GraphicsJobs: 0 + - m_BuildTarget: QNX + m_GraphicsJobs: 0 + m_BuildTargetGraphicsJobMode: + - m_BuildTarget: PS4Player + m_GraphicsJobMode: 0 + - m_BuildTarget: XboxOnePlayer + m_GraphicsJobMode: 0 + m_BuildTargetGraphicsAPIs: + - m_BuildTarget: iOSSupport + m_APIs: 10000000 + m_Automatic: 1 + - m_BuildTarget: AndroidPlayer + m_APIs: 0b00000008000000 + m_Automatic: 0 m_BuildTargetVRSettings: - m_BuildTarget: Android m_Enabled: 0 m_Devices: - Oculus - - m_BuildTarget: Metro + - m_BuildTarget: Windows Store Apps m_Enabled: 0 m_Devices: [] - m_BuildTarget: N3DS @@ -287,35 +486,50 @@ PlayerSettings: - m_BuildTarget: XboxOne m_Enabled: 0 m_Devices: [] - - m_BuildTarget: iOS + - m_BuildTarget: iPhone m_Enabled: 0 m_Devices: [] - m_BuildTarget: tvOS m_Enabled: 0 m_Devices: [] + m_DefaultShaderChunkSizeInMB: 16 + m_DefaultShaderChunkCount: 0 openGLRequireES31: 0 openGLRequireES31AEP: 0 - webPlayerTemplate: APPLICATION:Default + openGLRequireES32: 0 m_TemplateCustomTags: {} - wiiUTitleID: 0005000011000000 - wiiUGroupID: 00010000 - wiiUCommonSaveSize: 4096 - wiiUAccountSaveSize: 2048 - wiiUOlvAccessKey: 0 - wiiUTinCode: 0 - wiiUJoinGameId: 0 - wiiUJoinGameModeMask: 0000000000000000 - wiiUCommonBossSize: 0 - wiiUAccountBossSize: 0 - wiiUAddOnUniqueIDs: [] - wiiUMainThreadStackSize: 3072 - wiiULoaderThreadStackSize: 1024 - wiiUSystemHeapSize: 128 - wiiUTVStartupScreen: {fileID: 0} - wiiUGamePadStartupScreen: {fileID: 0} - wiiUDrcBufferDisabled: 0 - wiiUProfilerLibPath: + mobileMTRendering: + VisionOS: 1 + iPhone: 1 + tvOS: 1 + m_BuildTargetGroupLightmapEncodingQuality: + - m_BuildTarget: Standalone + m_EncodingQuality: 1 + - m_BuildTarget: XboxOne + m_EncodingQuality: 1 + - m_BuildTarget: PS4 + m_EncodingQuality: 1 + - m_BuildTarget: GameCoreScarlett + m_EncodingQuality: 1 + - m_BuildTarget: GameCoreXboxOne + m_EncodingQuality: 1 + m_BuildTargetGroupHDRCubemapEncodingQuality: + - m_BuildTarget: Standalone + m_EncodingQuality: 2 + - m_BuildTarget: XboxOne + m_EncodingQuality: 2 + - m_BuildTarget: PS4 + m_EncodingQuality: 2 + - m_BuildTarget: GameCoreScarlett + m_EncodingQuality: 2 + - m_BuildTarget: GameCoreXboxOne + m_EncodingQuality: 2 + m_BuildTargetGroupLightmapSettings: [] + m_BuildTargetGroupLoadStoreDebugModeSettings: [] + m_BuildTargetNormalMapEncoding: [] + m_BuildTargetDefaultTextureCompressionFormat: [] playModeTestRunnerEnabled: 0 + runPlayModeTestAsEditModeTest: 0 actionOnDotNetUnhandledException: 1 enableInternalProfiler: 0 logObjCUncaughtExceptions: 1 @@ -323,13 +537,21 @@ PlayerSettings: cameraUsageDescription: locationUsageDescription: microphoneUsageDescription: + bluetoothUsageDescription: + macOSTargetOSVersion: 10.13.0 + switchNMETAOverride: switchNetLibKey: switchSocketMemoryPoolSize: 6144 switchSocketAllocatorPoolSize: 128 switchSocketConcurrencyLimit: 14 + switchScreenResolutionBehavior: 2 switchUseCPUProfiler: 0 + switchEnableFileSystemTrace: 0 + switchUseGOLDLinker: 0 + switchLTOSetting: 0 switchApplicationID: 0x0005000C10000001 switchNSODependencies: + switchCompilerFlags: switchTitleNames_0: switchTitleNames_1: switchTitleNames_2: @@ -345,6 +567,7 @@ PlayerSettings: switchTitleNames_12: switchTitleNames_13: switchTitleNames_14: + switchTitleNames_15: switchPublisherNames_0: switchPublisherNames_1: switchPublisherNames_2: @@ -360,6 +583,7 @@ PlayerSettings: switchPublisherNames_12: switchPublisherNames_13: switchPublisherNames_14: + switchPublisherNames_15: switchIcons_0: {fileID: 0} switchIcons_1: {fileID: 0} switchIcons_2: {fileID: 0} @@ -375,6 +599,7 @@ PlayerSettings: switchIcons_12: {fileID: 0} switchIcons_13: {fileID: 0} switchIcons_14: {fileID: 0} + switchIcons_15: {fileID: 0} switchSmallIcons_0: {fileID: 0} switchSmallIcons_1: {fileID: 0} switchSmallIcons_2: {fileID: 0} @@ -390,6 +615,7 @@ PlayerSettings: switchSmallIcons_12: {fileID: 0} switchSmallIcons_13: {fileID: 0} switchSmallIcons_14: {fileID: 0} + switchSmallIcons_15: {fileID: 0} switchManualHTML: switchAccessibleURLs: switchLegalInformation: @@ -399,13 +625,12 @@ PlayerSettings: switchReleaseVersion: 0 switchDisplayVersion: 1.0.0 switchStartupUserAccount: 0 - switchTouchScreenUsage: 0 switchSupportedLanguagesMask: 0 switchLogoType: 0 switchApplicationErrorCodeCategory: switchUserAccountSaveDataSize: 0 switchUserAccountSaveDataJournalSize: 0 - switchAttribute: 0 + switchApplicationAttribute: 0 switchCardSpecSize: 4 switchCardSpecClock: 25 switchRatingsMask: 0 @@ -421,6 +646,7 @@ PlayerSettings: switchRatingsInt_9: 0 switchRatingsInt_10: 0 switchRatingsInt_11: 0 + switchRatingsInt_12: 0 switchLocalCommunicationIds_0: 0x0005000C10000001 switchLocalCommunicationIds_1: switchLocalCommunicationIds_2: @@ -431,7 +657,32 @@ PlayerSettings: switchLocalCommunicationIds_7: switchParentalControl: 0 switchAllowsScreenshot: 1 + switchAllowsVideoCapturing: 1 + switchAllowsRuntimeAddOnContentInstall: 0 switchDataLossConfirmation: 0 + switchUserAccountLockEnabled: 0 + switchSystemResourceMemory: 16777216 + switchSupportedNpadStyles: 22 + switchNativeFsCacheSize: 32 + switchIsHoldTypeHorizontal: 1 + switchSupportedNpadCount: 8 + switchEnableTouchScreen: 1 + switchSocketConfigEnabled: 0 + switchTcpInitialSendBufferSize: 32 + switchTcpInitialReceiveBufferSize: 64 + switchTcpAutoSendBufferSizeMax: 256 + switchTcpAutoReceiveBufferSizeMax: 256 + switchUdpSendBufferSize: 9 + switchUdpReceiveBufferSize: 42 + switchSocketBufferEfficiency: 4 + switchSocketInitializeEnabled: 1 + switchNetworkInterfaceManagerInitializeEnabled: 1 + switchUseNewStyleFilepaths: 1 + switchUseLegacyFmodPriorities: 0 + switchUseMicroSleepForYield: 1 + switchEnableRamDiskSupport: 0 + switchMicroSleepForYieldTime: 25 + switchRamDiskSpaceSize: 12 ps4NPAgeRating: 12 ps4NPTitleSecret: ps4NPTrophyPackPath: @@ -450,12 +701,15 @@ PlayerSettings: ps4PronunciationSIGPath: ps4BackgroundImagePath: ps4StartupImagePath: + ps4StartupImagesFolder: + ps4IconImagesFolder: ps4SaveDataImagePath: ps4SdkOverride: ps4BGMPath: ps4ShareFilePath: ps4ShareOverlayImagePath: ps4PrivacyGuardImagePath: + ps4ExtraSceSysFile: ps4NPtitleDatPath: ps4RemotePlayKeyAssignment: -1 ps4RemotePlayKeyMappingDir: @@ -468,17 +722,20 @@ PlayerSettings: ps4DownloadDataSize: 0 ps4GarlicHeapSize: 2048 ps4ProGarlicHeapSize: 2560 + playerPrefsMaxSize: 32768 ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ - ps4UseDebugIl2cppLibs: 0 ps4pnSessions: 1 ps4pnPresence: 1 ps4pnFriends: 1 ps4pnGameCustomData: 1 playerPrefsSupport: 0 + enableApplicationExit: 0 + resetTempFolder: 1 restrictedAudioUsageRights: 0 ps4UseResolutionFallback: 0 ps4ReprojectionSupport: 0 ps4UseAudio3dBackend: 0 + ps4UseLowGarlicFragmentationMode: 1 ps4SocialScreenEnabled: 0 ps4ScriptOptimizationLevel: 3 ps4Audio3dVirtualSpeakerCount: 14 @@ -495,63 +752,21 @@ PlayerSettings: ps4disableAutoHideSplash: 0 ps4videoRecordingFeaturesUsed: 0 ps4contentSearchFeaturesUsed: 0 + ps4CompatibilityPS5: 0 + ps4AllowPS5Detection: 0 + ps4GPU800MHz: 1 ps4attribEyeToEyeDistanceSettingVR: 0 ps4IncludedModules: [] + ps4attribVROutputEnabled: 0 monoEnv: - psp2Splashimage: {fileID: 0} - psp2NPTrophyPackPath: - psp2NPSupportGBMorGJP: 0 - psp2NPAgeRating: 12 - psp2NPTitleDatPath: - psp2NPCommsID: - psp2NPCommunicationsID: - psp2NPCommsPassphrase: - psp2NPCommsSig: - psp2ParamSfxPath: - psp2ManualPath: - psp2LiveAreaGatePath: - psp2LiveAreaBackroundPath: - psp2LiveAreaPath: - psp2LiveAreaTrialPath: - psp2PatchChangeInfoPath: - psp2PatchOriginalPackage: - psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui - psp2KeystoneFile: - psp2MemoryExpansionMode: 0 - psp2DRMType: 0 - psp2StorageType: 0 - psp2MediaCapacity: 0 - psp2DLCConfigPath: - psp2ThumbnailPath: - psp2BackgroundPath: - psp2SoundPath: - psp2TrophyCommId: - psp2TrophyPackagePath: - psp2PackagedResourcesPath: - psp2SaveDataQuota: 10240 - psp2ParentalLevel: 1 - psp2ShortTitle: Not Set - psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF - psp2Category: 0 - psp2MasterVersion: 01.00 - psp2AppVersion: 01.00 - psp2TVBootMode: 0 - psp2EnterButtonAssignment: 2 - psp2TVDisableEmu: 0 - psp2AllowTwitterDialog: 1 - psp2Upgradable: 0 - psp2HealthWarning: 0 - psp2UseLibLocation: 0 - psp2InfoBarOnStartup: 0 - psp2InfoBarColor: 0 - psp2UseDebugIl2cppLibs: 0 - psmSplashimage: {fileID: 0} splashScreenBackgroundSourceLandscape: {fileID: 0} splashScreenBackgroundSourcePortrait: {fileID: 0} + blurSplashScreenBackground: 1 spritePackerPolicy: webGLMemorySize: 256 webGLExceptionSupport: 1 webGLNameFilesAsHashes: 0 + webGLShowDiagnostics: 0 webGLDataCaching: 0 webGLDebugSymbols: 0 webGLEmscriptenArgs: @@ -559,19 +774,53 @@ PlayerSettings: webGLTemplate: APPLICATION:Default webGLAnalyzeBuildSize: 0 webGLUseEmbeddedResources: 0 - webGLUseWasm: 0 webGLCompressionFormat: 1 + webGLWasmArithmeticExceptions: 0 + webGLLinkerTarget: 1 + webGLThreadsSupport: 0 + webGLDecompressionFallback: 0 + webGLInitialMemorySize: 32 + webGLMaximumMemorySize: 2048 + webGLMemoryGrowthMode: 2 + webGLMemoryLinearGrowthStep: 16 + webGLMemoryGeometricGrowthStep: 0.2 + webGLMemoryGeometricGrowthCap: 96 + webGLPowerPreference: 2 scriptingDefineSymbols: - 7: UNITY + Android: UNITY + additionalCompilerArguments: {} platformArchitecture: {} scriptingBackend: Android: 0 - Metro: 2 Standalone: 0 WebGL: 1 WebPlayer: 0 + Windows Store Apps: 2 + il2cppCompilerConfiguration: {} + il2cppCodeGeneration: {} + managedStrippingLevel: + EmbeddedLinux: 1 + GameCoreScarlett: 1 + GameCoreXboxOne: 1 + Nintendo Switch: 1 + PS4: 1 + PS5: 1 + QNX: 1 + Stadia: 1 + VisionOS: 1 + WebGL: 1 + Windows Store Apps: 1 + XboxOne: 1 + iPhone: 1 + tvOS: 1 incrementalIl2cppBuild: {} + suppressCommonWarnings: 1 + allowUnsafeCode: 0 + useDeterministicCompilation: 1 additionalIl2CppArgs: + scriptingRuntimeVersion: 1 + gcIncremental: 1 + gcWBarrierValidation: 0 apiCompatibilityLevelPerPlatform: {} m_RenderingPath: 1 m_MobileRenderingPath: 1 @@ -585,11 +834,12 @@ PlayerSettings: metroApplicationDescription: LiteNetLibSampleUnity wsaImages: {} metroTileShortName: - metroCommandLineArgsFile: metroTileShowName: 0 metroMediumTileShowName: 0 metroLargeTileShowName: 0 metroWideTileShowName: 0 + metroSupportStreamingInstall: 0 + metroLastRequiredScene: 0 metroDefaultTileSize: 1 metroTileForegroundText: 1 metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} @@ -597,35 +847,11 @@ PlayerSettings: a: 1} metroSplashScreenUseBackgroundColor: 1 platformCapabilities: {} + metroTargetDeviceFamilies: {} metroFTAName: metroFTAFileTypes: [] metroProtocolName: - metroCompilationOverrides: 1 - tizenProductDescription: - tizenProductURL: - tizenSigningProfileName: - tizenGPSPermissions: 0 - tizenMicrophonePermissions: 0 - tizenDeploymentTarget: - tizenDeploymentTargetType: -1 - tizenMinOSVersion: 1 - n3dsUseExtSaveData: 0 - n3dsCompressStaticMem: 1 - n3dsExtSaveDataNumber: 0x12345 - n3dsStackSize: 131072 - n3dsTargetPlatform: 2 - n3dsRegion: 7 - n3dsMediaSize: 0 - n3dsLogoStyle: 3 - n3dsTitle: GameName - n3dsProductCode: - n3dsApplicationId: 0xFF3FF - stvDeviceAddress: - stvProductDescription: - stvProductAuthor: - stvProductAuthorEmail: - stvProductLink: - stvProductCategory: 0 + vcxProjDefaultLanguage: XboxOneProductId: XboxOneUpdateKey: XboxOneSandboxId: @@ -635,6 +861,7 @@ PlayerSettings: XboxOneGameOsOverridePath: XboxOnePackagingOverridePath: XboxOneAppManifestOverridePath: + XboxOneVersion: 1.0.0.0 XboxOnePackageEncryption: 0 XboxOnePackageUpdateGranularity: 2 XboxOneDescription: @@ -643,16 +870,16 @@ PlayerSettings: XboxOneCapability: [] XboxOneGameRating: {} XboxOneIsContentPackage: 0 + XboxOneEnhancedXboxCompatibilityMode: 0 XboxOneEnableGPUVariability: 0 XboxOneSockets: {} XboxOneSplashScreen: {fileID: 0} XboxOneAllowedProductIds: [] XboxOnePersistentLocalStorageSize: 0 - xboxOneScriptCompiler: 0 - vrEditorSettings: - daydream: - daydreamIconForeground: {fileID: 0} - daydreamIconBackground: {fileID: 0} + XboxOneXTitleMemory: 8 + XboxOneOverrideIdentityName: + XboxOneOverrideIdentityPublisher: + vrEditorSettings: {} cloudServicesEnabled: Analytics: 0 Build: 0 @@ -663,10 +890,33 @@ PlayerSettings: Purchasing: 0 UNet: 0 Unity_Ads: 0 - facebookSdkVersion: 7.9.1 - apiCompatibilityLevel: 2 + luminIcon: + m_Name: + m_ModelFolderPath: + m_PortalFolderPath: + luminCert: + m_CertPath: + m_SignPackage: 1 + luminIsChannelApp: 0 + luminVersion: + m_VersionCode: 1 + m_VersionName: + hmiPlayerDataPath: + hmiForceSRGBBlit: 1 + embeddedLinuxEnableGamepadInput: 1 + hmiLogStartupTiming: 0 + hmiCpuConfiguration: + apiCompatibilityLevel: 6 + activeInputHandler: 0 + windowsGamepadBackendHint: 0 cloudProjectId: + framebufferDepthMemorylessMode: 0 + qualitySettingsNames: [] projectName: organizationId: cloudEnabled: 0 - enableNewInputSystem: 0 + legacyClampBlendShapeWeights: 1 + hmiLoadingImage: {fileID: 0} + platformRequiresReadableAssets: 0 + virtualTexturingSupportEnabled: 0 + insecureHttpOption: 0 diff --git a/LiteNetLibSampleUnity/ProjectSettings/ProjectVersion.txt b/LiteNetLibSampleUnity/ProjectSettings/ProjectVersion.txt index d848e35e..e4eac159 100644 --- a/LiteNetLibSampleUnity/ProjectSettings/ProjectVersion.txt +++ b/LiteNetLibSampleUnity/ProjectSettings/ProjectVersion.txt @@ -1 +1,2 @@ -m_EditorVersion: 2018.3.8f1 +m_EditorVersion: 2022.3.12f1 +m_EditorVersionWithRevision: 2022.3.12f1 (4fe6e059c7ef) diff --git a/LiteNetLibSampleUnity/ProjectSettings/VFXManager.asset b/LiteNetLibSampleUnity/ProjectSettings/VFXManager.asset index 85b0821bd6112e21b75662df3a1fbc9df5dcbce7..852348bcbdefc6ca66eed4c68cf7c2a6d22a0f22 100644 GIT binary patch literal 465 zcmZ{g&2ED*5QOhMg>y(xC4!*Rgj;?}8!4y}PNVizId}nAU@WspK~>+q#!)U+@o~Nx zYj&m|t7K37neR-Gt7kIlCInd#by8p-@LAT>_jAwpBgb{!fi8o`Ae@KG1-bK`Q~aJV z$qLYsLrDGkdj5h8Uj&D^VnrJf&&oT=g*Jeej2kQY&P4^gt-(K*ZyMFFyF3Ry=Aexp zO;glDy(!KR#^O)4!hQ^8U zJ2(b)#x)z(ndoytdpPGgdiH_uh-0#jNTT9o&hHT0%%l3gOW5K2PBYgTr6bHk__BackingField: 0 + k__BackingField: -1 + m_GroupName: + - rid: 7267259948770525185 + type: {class: GPUProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.GPUProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ViewType: 0 + updateViewLive: 0 + m_CurrentFrameIndex: -1 + m_HierarchyOverruledThreadFromSelection: 0 + m_ProfilerViewFilteringOptions: 1 + m_FrameDataHierarchyView: + m_Serialized: 0 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_ThreadIndexInThreadNames: 0 + m_DetailedViewType: 0 + m_DetailedViewSpliterState: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedObjectsView: + m_SelectedID: 0 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedCallsView: + m_SelectedID: 0 + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_CalleesTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_CallersTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_FullThreadName: Main Thread + m_ThreadName: Main Thread + k__BackingField: 0 + k__BackingField: -1 + m_GroupName: + - rid: 7267259948770525186 + type: {class: RenderingProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.RenderingProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525187 + type: {class: MemoryProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.MemoryProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ViewSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: -1 + realSizes: + - 0 + - 0 + relativeSizes: + - 0.7 + - 0.3 + minSizes: + - 450 + - 50 + maxSizes: + - 0 + - 0 + lastTotalSize: 0 + splitSize: 6 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + - rid: 7267259948770525188 + type: {class: AudioProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.AudioProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ShowInactiveDSPChains: 0 + m_HighlightAudibleDSPChains: 1 + m_DSPGraphZoomFactor: 1 + m_DSPGraphHorizontalLayout: 0 + - rid: 7267259948770525189 + type: {class: VideoProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.VideoProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525190 + type: {class: PhysicsProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.PhysicsProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525191 + type: {class: Physics2DProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.Physics2DProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525192 + type: {class: UIProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.UIProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525193 + type: {class: UIDetailsProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.UIDetailsProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525194 + type: {class: GlobalIlluminationProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.GlobalIlluminationProfilerModule, + UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525195 + type: {class: VirtualTexturingProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.VirtualTexturingProfilerModule, + UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_VTProfilerView: + rid: 7267259948770525198 + - rid: 7267259948770525196 + type: {class: FileIOProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.FileIOProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525197 + type: {class: AssetLoadingProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.AssetLoadingProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525198 + type: {class: VirtualTexturingProfilerView, ns: UnityEditor, asm: UnityEditor.CoreModule} + data: + m_SortAscending: 0 + m_SortedColumn: -1 +--- !u!114 &8 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 9} + - {fileID: 11} + m_Position: + serializedVersion: 2 + x: 1493 + y: 0 + width: 376 + height: 1299 + m_MinSize: {x: 100, y: 100} + m_MaxSize: {x: 8096, y: 16192} + vertical: 1 + controlID: 338 +--- !u!114 &9 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: SceneHierarchyWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 376 + height: 624 + m_MinSize: {x: 202, y: 221} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 10} + m_Panes: + - {fileID: 10} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &10 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Hierarchy + m_Image: {fileID: 7966133145522015247, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1493 + y: 73 + width: 374 + height: 603 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_SceneHierarchy: + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: 1638ffff1a3cffff + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 9} + m_SearchString: + m_ExpandedScenes: [] + m_CurrenRootInstanceID: 0 + m_LockTracker: + m_IsLocked: 0 + m_CurrentSortingName: TransformSorting + m_WindowGUID: 5744dfe58afd7b349b2bf692722dc4ff +--- !u!114 &11 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: ProjectBrowser + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 624 + width: 376 + height: 675 + m_MinSize: {x: 232, y: 271} + m_MaxSize: {x: 10002, y: 10021} + m_ActualView: {fileID: 12} + m_Panes: + - {fileID: 12} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &12 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 230, y: 250} + m_MaxSize: {x: 10000, y: 10000} + m_TitleContent: + m_Text: Project + m_Image: {fileID: -5467254957812901981, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1493 + y: 697 + width: 374 + height: 654 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_SearchFilter: + m_NameFilter: + m_ClassNames: [] + m_AssetLabels: [] + m_AssetBundleNames: [] + m_ReferencingInstanceIDs: + m_SceneHandles: + m_ShowAllHits: 0 + m_SkipHidden: 0 + m_SearchArea: 1 + m_Folders: + - Assets + m_Globs: [] + m_OriginalText: + m_ImportLogFlags: 0 + m_FilterByTypeIntersection: 0 + m_ViewMode: 0 + m_StartGridSize: 16 + m_LastFolders: [] + m_LastFoldersGridSize: -1 + m_LastProjectPath: E:\Projects\LiteNetLib\LiteNetLibSampleUnity + m_LockTracker: + m_IsLocked: 0 + m_FolderTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 0e800000 + m_LastClickedID: 32782 + m_ExpandedIDs: ffffffffd0400000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_AssetTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 887a0000 + m_LastClickedID: 31368 + m_ExpandedIDs: ffffffffd0400000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 11} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_ListAreaState: + m_SelectedInstanceIDs: 887a0000 + m_LastClickedInstanceID: 31368 + m_HadKeyboardFocusLastEvent: 0 + m_ExpandedInstanceIDs: c6230000d0640000967900008e6d00007674000022740000a66f000000000000687100009c230000f4b70000288000007a5f00008e7d0000ecbc0000346d0000f09c0000c297000026850000f06c0000de7d0000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 11} + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_NewAssetIndexInList: -1 + m_ScrollPosition: {x: 0, y: 0} + m_GridSize: 16 + m_SkipHiddenPackages: 0 + m_DirectoriesAreaWidth: 178 +--- !u!114 &13 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: InspectorWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 1869 + y: 0 + width: 691 + height: 1299 + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} + m_ActualView: {fileID: 14} + m_Panes: + - {fileID: 14} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &14 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Inspector + m_Image: {fileID: -2667387946076563598, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1869 + y: 73 + width: 690 + height: 1278 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_ObjectsLockedBeforeSerialization: [] + m_InstanceIDsLockedBeforeSerialization: + m_PreviewResizer: + m_CachedPref: 526 + m_ControlHash: -371814159 + m_PrefName: Preview_InspectorPreview + m_LastInspectedObjectInstanceID: 31368 + m_LastVerticalScrollValue: 0 + m_GlobalObjectId: + m_InspectorMode: 0 + m_LockTracker: + m_IsLocked: 0 + m_PreviewWindow: {fileID: 0} diff --git a/LiteNetLibSampleUnity/UserSettings/Layouts/default-2022.dwlt b/LiteNetLibSampleUnity/UserSettings/Layouts/default-2022.dwlt new file mode 100644 index 00000000..bea9ed68 --- /dev/null +++ b/LiteNetLibSampleUnity/UserSettings/Layouts/default-2022.dwlt @@ -0,0 +1,2095 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &1 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12004, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_PixelRect: + serializedVersion: 2 + x: 0 + y: 43 + width: 2560 + height: 1349 + m_ShowMode: 4 + m_Title: Profiler + m_RootView: {fileID: 2} + m_MinSize: {x: 875, y: 421} + m_MaxSize: {x: 10000, y: 10000} + m_Maximized: 1 +--- !u!114 &2 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12008, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 3} + - {fileID: 5} + - {fileID: 4} + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 2560 + height: 1349 + m_MinSize: {x: 875, y: 300} + m_MaxSize: {x: 10000, y: 10000} + m_UseTopView: 1 + m_TopViewHeight: 30 + m_UseBottomView: 1 + m_BottomViewHeight: 20 +--- !u!114 &3 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12011, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 2560 + height: 30 + m_MinSize: {x: 0, y: 0} + m_MaxSize: {x: 0, y: 0} + m_LastLoadedLayoutName: +--- !u!114 &4 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12042, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 1329 + width: 2560 + height: 20 + m_MinSize: {x: 0, y: 0} + m_MaxSize: {x: 0, y: 0} +--- !u!114 &5 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 6} + - {fileID: 9} + - {fileID: 12} + m_Position: + serializedVersion: 2 + x: 0 + y: 30 + width: 2560 + height: 1299 + m_MinSize: {x: 300, y: 100} + m_MaxSize: {x: 24288, y: 16192} + vertical: 0 + controlID: 684 +--- !u!114 &6 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 7} + - {fileID: 8} + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 1493 + height: 1299 + m_MinSize: {x: 100, y: 100} + m_MaxSize: {x: 8096, y: 16192} + vertical: 1 + controlID: 690 +--- !u!114 &7 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: GameView + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 1493 + height: 733 + m_MinSize: {x: 201, y: 221} + m_MaxSize: {x: 4001, y: 4021} + m_ActualView: {fileID: 13} + m_Panes: + - {fileID: 14} + - {fileID: 13} + m_Selected: 1 + m_LastSelected: 0 +--- !u!114 &8 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: ProfilerWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 733 + width: 1493 + height: 566 + m_MinSize: {x: 901, y: 237} + m_MaxSize: {x: 4001, y: 4021} + m_ActualView: {fileID: 15} + m_Panes: + - {fileID: 15} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &9 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12010, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_Children: + - {fileID: 10} + - {fileID: 11} + m_Position: + serializedVersion: 2 + x: 1493 + y: 0 + width: 376 + height: 1299 + m_MinSize: {x: 100, y: 100} + m_MaxSize: {x: 8096, y: 16192} + vertical: 1 + controlID: 635 +--- !u!114 &10 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: SceneHierarchyWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 0 + width: 376 + height: 624 + m_MinSize: {x: 202, y: 221} + m_MaxSize: {x: 4002, y: 4021} + m_ActualView: {fileID: 16} + m_Panes: + - {fileID: 16} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &11 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: ProjectBrowser + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 0 + y: 624 + width: 376 + height: 675 + m_MinSize: {x: 232, y: 271} + m_MaxSize: {x: 10002, y: 10021} + m_ActualView: {fileID: 17} + m_Panes: + - {fileID: 17} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &12 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12006, guid: 0000000000000000e000000000000000, type: 0} + m_Name: InspectorWindow + m_EditorClassIdentifier: + m_Children: [] + m_Position: + serializedVersion: 2 + x: 1869 + y: 0 + width: 691 + height: 1299 + m_MinSize: {x: 276, y: 71} + m_MaxSize: {x: 4001, y: 4021} + m_ActualView: {fileID: 18} + m_Panes: + - {fileID: 18} + m_Selected: 0 + m_LastSelected: 0 +--- !u!114 &13 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12015, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Game + m_Image: {fileID: -6423792434712278376, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 0 + y: 73 + width: 1492 + height: 712 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_SerializedViewNames: [] + m_SerializedViewValues: [] + m_PlayModeViewName: GameView + m_ShowGizmos: 0 + m_TargetDisplay: 0 + m_ClearColor: {r: 0, g: 0, b: 0, a: 0} + m_TargetSize: {x: 1228, y: 691} + m_TextureFilterMode: 0 + m_TextureHideFlags: 61 + m_RenderIMGUI: 1 + m_EnterPlayModeBehavior: 0 + m_UseMipMap: 0 + m_VSyncEnabled: 1 + m_Gizmos: 0 + m_Stats: 0 + m_SelectedSizes: 0100000000000000000000000e000000000000000000000000000000000000000000000000000000 + m_ZoomArea: + m_HRangeLocked: 0 + m_VRangeLocked: 0 + hZoomLockedByDefault: 0 + vZoomLockedByDefault: 0 + m_HBaseRangeMin: -614 + m_HBaseRangeMax: 614 + m_VBaseRangeMin: -345.5 + m_VBaseRangeMax: 345.5 + m_HAllowExceedBaseRangeMin: 1 + m_HAllowExceedBaseRangeMax: 1 + m_VAllowExceedBaseRangeMin: 1 + m_VAllowExceedBaseRangeMax: 1 + m_ScaleWithWindow: 0 + m_HSlider: 0 + m_VSlider: 0 + m_IgnoreScrollWheelUntilClicked: 0 + m_EnableMouseInput: 1 + m_EnableSliderZoomHorizontal: 0 + m_EnableSliderZoomVertical: 0 + m_UniformScale: 1 + m_UpDirection: 1 + m_DrawArea: + serializedVersion: 2 + x: 0 + y: 21 + width: 1492 + height: 691 + m_Scale: {x: 1, y: 1} + m_Translation: {x: 746, y: 345.5} + m_MarginLeft: 0 + m_MarginRight: 0 + m_MarginTop: 0 + m_MarginBottom: 0 + m_LastShownAreaInsideMargins: + serializedVersion: 2 + x: -746 + y: -345.5 + width: 1492 + height: 691 + m_MinimalGUI: 1 + m_defaultScale: 1 + m_LastWindowPixelSize: {x: 1492, y: 712} + m_ClearInEditMode: 1 + m_NoCameraWarning: 1 + m_LowResolutionForAspectRatios: 01000001000000000000 + m_XRRenderMode: 0 + m_RenderTexture: {fileID: 0} +--- !u!114 &14 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12013, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Scene + m_Image: {fileID: 2593428753322112591, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 0 + y: 73 + width: 1492 + height: 845 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: + - dockPosition: 0 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: -166, y: -26} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 3 + id: Tool Settings + index: 0 + layout: 1 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 0 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: -141, y: 149} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 1 + id: unity-grid-and-snap-toolbar + index: 1 + layout: 1 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 25} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: unity-scene-view-toolbar + index: 0 + layout: 1 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-toolbar__top + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 1 + id: unity-search-toolbar + index: 1 + layout: 1 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 0 + containerId: overlay-container--left + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 25} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: unity-transform-toolbar + index: 0 + layout: 2 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 0 + containerId: overlay-container--left + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 0, y: 197} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: unity-component-tools + index: 1 + layout: 2 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 0 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 67.5, y: -123} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 2 + id: Orientation + index: 0 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Light Settings + index: 2 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Camera + index: 1 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Cloth Constraints + index: 3 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Cloth Collisions + index: 4 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Navmesh Display + index: 4 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Agent Display + index: 5 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Obstacle Display + index: 6 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Occlusion Culling + index: 5 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Physics Debugger + index: 6 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Scene Visibility + index: 7 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 25} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Particles + index: 8 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Tilemap + index: 11 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 0, y: 0} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Tilemap Palette Helper + index: 12 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: -216, y: -156} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 3 + id: AINavigationOverlay + index: 9 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 48, y: 48} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: APV Overlay + index: 8 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 48, y: 48} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/TrailRenderer + index: 10 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 1 + snapOffset: {x: 48, y: 10} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: UnityEditor.SceneViewCameraOverlay + index: 10 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 48, y: 48} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Open Tile Palette + index: 0 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + - dockPosition: 1 + containerId: overlay-container--right + floating: 0 + collapsed: 0 + displayed: 0 + snapOffset: {x: 48, y: 48} + snapOffsetDelta: {x: 0, y: 0} + snapCorner: 0 + id: Scene View/Tilemap Focus + index: 1 + layout: 4 + size: {x: 0, y: 0} + sizeOverriden: 0 + m_OverlaysVisible: 1 + m_WindowGUID: c9ee0d44a80756c48ba1fd3e952ef1b5 + m_Gizmos: 1 + m_OverrideSceneCullingMask: 6917529027641081856 + m_SceneIsLit: 1 + m_SceneLighting: 1 + m_2DMode: 0 + m_isRotationLocked: 0 + m_PlayAudio: 0 + m_AudioPlay: 0 + m_Position: + m_Target: {x: 0, y: 0, z: 0} + speed: 2 + m_Value: {x: 0, y: 0, z: 0} + m_RenderMode: 0 + m_CameraMode: + drawMode: 0 + name: Shaded + section: Shading Mode + m_ValidateTrueMetals: 0 + m_DoValidateTrueMetals: 0 + m_SceneViewState: + m_AlwaysRefresh: 0 + showFog: 1 + showSkybox: 1 + showFlares: 1 + showImageEffects: 1 + showParticleSystems: 1 + showVisualEffectGraphs: 1 + m_FxEnabled: 1 + m_Grid: + xGrid: + m_Fade: + m_Target: 0 + speed: 2 + m_Value: 0 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 0, y: 0} + yGrid: + m_Fade: + m_Target: 1 + speed: 2 + m_Value: 1 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 1, y: 1} + zGrid: + m_Fade: + m_Target: 0 + speed: 2 + m_Value: 0 + m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 0.4} + m_Pivot: {x: 0, y: 0, z: 0} + m_Size: {x: 1, y: 1} + m_ShowGrid: 1 + m_GridAxis: 1 + m_gridOpacity: 0.5 + m_Rotation: + m_Target: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + speed: 2 + m_Value: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + m_Size: + m_Target: 10 + speed: 2 + m_Value: 10 + m_Ortho: + m_Target: 0 + speed: 2 + m_Value: 0 + m_CameraSettings: + m_Speed: 0.8856 + m_SpeedNormalized: 0.44 + m_SpeedMin: 0.01 + m_SpeedMax: 2 + m_EasingEnabled: 1 + m_EasingDuration: 0.4 + m_AccelerationEnabled: 1 + m_FieldOfViewHorizontalOrVertical: 60 + m_NearClip: 0.03 + m_FarClip: 10000 + m_DynamicClip: 1 + m_OcclusionCulling: 0 + m_LastSceneViewRotation: {x: -0.08717229, y: 0.89959055, z: -0.21045254, w: -0.3726226} + m_LastSceneViewOrtho: 0 + m_ReplacementShader: {fileID: 0} + m_ReplacementString: + m_SceneVisActive: 1 + m_LastLockedObject: {fileID: 0} + m_ViewIsLockedToObject: 0 +--- !u!114 &15 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 12070, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 900, y: 216} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Profiler + m_Image: {fileID: -1089619856830078684, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 0 + y: 806 + width: 1492 + height: 545 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_Recording: 1 + m_ActiveNativePlatformSupportModuleName: + m_AllModules: + - rid: 7267259948770525184 + - rid: 7267259948770525185 + - rid: 7267259948770525186 + - rid: 7267259948770525187 + - rid: 7267259948770525188 + - rid: 7267259948770525189 + - rid: 7267259948770525190 + - rid: 7267259948770525191 + - rid: 7267259948770525192 + - rid: 7267259948770525193 + - rid: 7267259948770525194 + - rid: 7267259948770525195 + - rid: 7267259948770525196 + - rid: 7267259948770525197 + m_CallstackRecordMode: 1 + m_ClearOnPlay: 0 + references: + version: 2 + RefIds: + - rid: 7267259948770525184 + type: {class: CPUProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.CPUProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ViewType: 0 + updateViewLive: 0 + m_CurrentFrameIndex: 1103 + m_HierarchyOverruledThreadFromSelection: 0 + m_ProfilerViewFilteringOptions: 1 + m_FrameDataHierarchyView: + m_Serialized: 1 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 8b000000 + m_LastClickedID: 139 + m_ExpandedIDs: 040000003a0000008b000000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: + - width: 200 + sortedAscending: 1 + headerContent: + m_Text: Overview + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 200 + maxWidth: 1000000 + autoResize: 1 + allowToggleVisibility: 0 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: Total + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: Self + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: Calls + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: GC Alloc + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: Time ms + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 80 + sortedAscending: 0 + headerContent: + m_Text: Self ms + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 50 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 25 + sortedAscending: 0 + headerContent: + m_Text: + m_Image: {fileID: -5161429177145976760, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: Warnings + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 25 + maxWidth: 25 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + m_VisibleColumns: 0000000001000000020000000300000004000000050000000600000007000000 + m_SortedColumns: 05000000 + m_ThreadIndexInThreadNames: 0 + m_DetailedViewType: 0 + m_DetailedViewSpliterState: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: -1 + realSizes: + - 0 + - 0 + relativeSizes: + - 0.7 + - 0.3 + minSizes: + - 450 + - 50 + maxSizes: + - 0 + - 0 + lastTotalSize: 0 + splitSize: 6 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedObjectsView: + m_SelectedID: -1 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedCallsView: + m_SelectedID: -1 + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_CalleesTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: + - width: 150 + sortedAscending: 1 + headerContent: + m_Text: Called From + m_Image: {fileID: 0} + m_Tooltip: 'Parents the selected function is called from + + + (Press + ''F'' for frame selection)' + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 150 + maxWidth: 1000000 + autoResize: 1 + allowToggleVisibility: 0 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Calls + m_Image: {fileID: 0} + m_Tooltip: Total number of calls in a selected frame + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: GC Alloc + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time ms + m_Image: {fileID: 0} + m_Tooltip: Total time the selected function spends within a parent + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time % + m_Image: {fileID: 0} + m_Tooltip: Shows how often the selected function was called from + the parent call + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + m_VisibleColumns: 0000000001000000020000000300000004000000 + m_SortedColumns: 03000000 + m_CallersTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: + - width: 150 + sortedAscending: 1 + headerContent: + m_Text: Called From + m_Image: {fileID: 0} + m_Tooltip: 'Parents the selected function is called from + + + (Press + ''F'' for frame selection)' + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 150 + maxWidth: 1000000 + autoResize: 1 + allowToggleVisibility: 0 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Calls + m_Image: {fileID: 0} + m_Tooltip: Total number of calls in a selected frame + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: GC Alloc + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time ms + m_Image: {fileID: 0} + m_Tooltip: Total time the selected function spends within a parent + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time % + m_Image: {fileID: 0} + m_Tooltip: Shows how often the selected function was called from + the parent call + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + m_VisibleColumns: 0000000001000000020000000300000004000000 + m_SortedColumns: 03000000 + m_FullThreadName: Main Thread + m_ThreadName: Main Thread + k__BackingField: 1059876 + k__BackingField: 0 + m_GroupName: + - rid: 7267259948770525185 + type: {class: GPUProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.GPUProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ViewType: 0 + updateViewLive: 0 + m_CurrentFrameIndex: -1 + m_HierarchyOverruledThreadFromSelection: 0 + m_ProfilerViewFilteringOptions: 1 + m_FrameDataHierarchyView: + m_Serialized: 0 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_ThreadIndexInThreadNames: 0 + m_DetailedViewType: 0 + m_DetailedViewSpliterState: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedObjectsView: + m_SelectedID: 0 + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_MultiColumnHeaderState: + m_Columns: [] + m_VisibleColumns: + m_SortedColumns: + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_DetailedCallsView: + m_SelectedID: -1 + m_VertSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: 0 + realSizes: [] + relativeSizes: [] + minSizes: [] + maxSizes: [] + lastTotalSize: 0 + splitSize: 0 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + m_CalleesTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: + - width: 150 + sortedAscending: 1 + headerContent: + m_Text: Called From + m_Image: {fileID: 0} + m_Tooltip: 'Parents the selected function is called from + + + (Press + ''F'' for frame selection)' + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 150 + maxWidth: 1000000 + autoResize: 1 + allowToggleVisibility: 0 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Calls + m_Image: {fileID: 0} + m_Tooltip: Total number of calls in a selected frame + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: GC Alloc + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time ms + m_Image: {fileID: 0} + m_Tooltip: Total time the selected function spends within a parent + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time % + m_Image: {fileID: 0} + m_Tooltip: Shows how often the selected function was called from + the parent call + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + m_VisibleColumns: 0000000001000000020000000300000004000000 + m_SortedColumns: 03000000 + m_CallersTreeView: + m_ViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_ViewHeaderState: + m_Columns: + - width: 150 + sortedAscending: 1 + headerContent: + m_Text: Called From + m_Image: {fileID: 0} + m_Tooltip: 'Parents the selected function is called from + + + (Press + ''F'' for frame selection)' + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 150 + maxWidth: 1000000 + autoResize: 1 + allowToggleVisibility: 0 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Calls + m_Image: {fileID: 0} + m_Tooltip: Total number of calls in a selected frame + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: GC Alloc + m_Image: {fileID: 0} + m_Tooltip: + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time ms + m_Image: {fileID: 0} + m_Tooltip: Total time the selected function spends within a parent + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + - width: 60 + sortedAscending: 0 + headerContent: + m_Text: Time % + m_Image: {fileID: 0} + m_Tooltip: Shows how often the selected function was called from + the parent call + contextMenuText: + headerTextAlignment: 0 + sortingArrowAlignment: 2 + minWidth: 60 + maxWidth: 1000000 + autoResize: 0 + allowToggleVisibility: 1 + canSort: 1 + userData: 0 + m_VisibleColumns: 0000000001000000020000000300000004000000 + m_SortedColumns: 03000000 + m_FullThreadName: Main Thread + m_ThreadName: Main Thread + k__BackingField: 0 + k__BackingField: -1 + m_GroupName: + - rid: 7267259948770525186 + type: {class: RenderingProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.RenderingProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525187 + type: {class: MemoryProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.MemoryProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ViewSplit: + ID: 0 + splitterInitialOffset: 0 + currentActiveSplitter: -1 + realSizes: + - 0 + - 0 + relativeSizes: + - 0.7 + - 0.3 + minSizes: + - 450 + - 50 + maxSizes: + - 0 + - 0 + lastTotalSize: 0 + splitSize: 6 + xOffset: 0 + m_Version: 1 + oldRealSizes: + oldMinSizes: + oldMaxSizes: + oldSplitSize: 0 + - rid: 7267259948770525188 + type: {class: AudioProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.AudioProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_ShowInactiveDSPChains: 0 + m_HighlightAudibleDSPChains: 1 + m_DSPGraphZoomFactor: 1 + m_DSPGraphHorizontalLayout: 0 + - rid: 7267259948770525189 + type: {class: VideoProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.VideoProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525190 + type: {class: PhysicsProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.PhysicsProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525191 + type: {class: Physics2DProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.Physics2DProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525192 + type: {class: UIProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.UIProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525193 + type: {class: UIDetailsProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.UIDetailsProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525194 + type: {class: GlobalIlluminationProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.GlobalIlluminationProfilerModule, + UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525195 + type: {class: VirtualTexturingProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.VirtualTexturingProfilerModule, + UnityEditor.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + m_VTProfilerView: + rid: 7267259948770525198 + - rid: 7267259948770525196 + type: {class: FileIOProfilerModule, ns: UnityEditorInternal.Profiling, asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.FileIOProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525197 + type: {class: AssetLoadingProfilerModule, ns: UnityEditorInternal.Profiling, + asm: UnityEditor.CoreModule} + data: + m_Identifier: UnityEditorInternal.Profiling.AssetLoadingProfilerModule, UnityEditor.CoreModule, + Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + m_PaneScroll: {x: 0, y: 0} + - rid: 7267259948770525198 + type: {class: VirtualTexturingProfilerView, ns: UnityEditor, asm: UnityEditor.CoreModule} + data: + m_SortAscending: 0 + m_SortedColumn: -1 +--- !u!114 &16 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12061, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 200, y: 200} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Hierarchy + m_Image: {fileID: 7966133145522015247, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1493 + y: 73 + width: 374 + height: 603 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_SceneHierarchy: + m_TreeViewState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 887a0000 + m_LastClickedID: 0 + m_ExpandedIDs: 1638ffff1a3cffff + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 0 + m_ClientGUIView: {fileID: 10} + m_SearchString: + m_ExpandedScenes: [] + m_CurrenRootInstanceID: 0 + m_LockTracker: + m_IsLocked: 0 + m_CurrentSortingName: TransformSorting + m_WindowGUID: 5744dfe58afd7b349b2bf692722dc4ff +--- !u!114 &17 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12014, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 230, y: 250} + m_MaxSize: {x: 10000, y: 10000} + m_TitleContent: + m_Text: Project + m_Image: {fileID: -5467254957812901981, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1493 + y: 697 + width: 374 + height: 654 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_SearchFilter: + m_NameFilter: + m_ClassNames: [] + m_AssetLabels: [] + m_AssetBundleNames: [] + m_ReferencingInstanceIDs: + m_SceneHandles: + m_ShowAllHits: 0 + m_SkipHidden: 0 + m_SearchArea: 1 + m_Folders: + - Assets + m_Globs: [] + m_OriginalText: + m_ImportLogFlags: 0 + m_FilterByTypeIntersection: 0 + m_ViewMode: 0 + m_StartGridSize: 16 + m_LastFolders: [] + m_LastFoldersGridSize: -1 + m_LastProjectPath: E:\Projects\LiteNetLib\LiteNetLibSampleUnity + m_LockTracker: + m_IsLocked: 0 + m_FolderTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: 0e800000 + m_LastClickedID: 32782 + m_ExpandedIDs: ffffffffd0400000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 0} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_AssetTreeState: + scrollPos: {x: 0, y: 0} + m_SelectedIDs: + m_LastClickedID: 0 + m_ExpandedIDs: ffffffffd0400000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 11} + m_SearchString: + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_ListAreaState: + m_SelectedInstanceIDs: + m_LastClickedInstanceID: 0 + m_HadKeyboardFocusLastEvent: 0 + m_ExpandedInstanceIDs: c6230000d0640000967900008e6d00007674000022740000a66f000000000000687100009c230000f4b70000288000007a5f00008e7d0000ecbc0000346d0000f09c0000c297000026850000f06c0000de7d0000 + m_RenameOverlay: + m_UserAcceptedRename: 0 + m_Name: + m_OriginalName: + m_EditFieldRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 0 + height: 0 + m_UserData: 0 + m_IsWaitingForDelay: 0 + m_IsRenaming: 0 + m_OriginalEventType: 11 + m_IsRenamingFilename: 1 + m_ClientGUIView: {fileID: 11} + m_CreateAssetUtility: + m_EndAction: {fileID: 0} + m_InstanceID: 0 + m_Path: + m_Icon: {fileID: 0} + m_ResourceFile: + m_NewAssetIndexInList: -1 + m_ScrollPosition: {x: 0, y: 0} + m_GridSize: 16 + m_SkipHiddenPackages: 0 + m_DirectoriesAreaWidth: 178 +--- !u!114 &18 +MonoBehaviour: + m_ObjectHideFlags: 52 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 1 + m_Script: {fileID: 12019, guid: 0000000000000000e000000000000000, type: 0} + m_Name: + m_EditorClassIdentifier: + m_MinSize: {x: 275, y: 50} + m_MaxSize: {x: 4000, y: 4000} + m_TitleContent: + m_Text: Inspector + m_Image: {fileID: -2667387946076563598, guid: 0000000000000000d000000000000000, + type: 0} + m_Tooltip: + m_Pos: + serializedVersion: 2 + x: 1869 + y: 73 + width: 690 + height: 1278 + m_SerializedDataModeController: + m_DataMode: 0 + m_PreferredDataMode: 0 + m_SupportedDataModes: + isAutomatic: 1 + m_ViewDataDictionary: {fileID: 0} + m_OverlayCanvas: + m_LastAppliedPresetName: Default + m_SaveData: [] + m_OverlaysVisible: 1 + m_ObjectsLockedBeforeSerialization: [] + m_InstanceIDsLockedBeforeSerialization: + m_PreviewResizer: + m_CachedPref: 526 + m_ControlHash: -371814159 + m_PrefName: Preview_InspectorPreview + m_LastInspectedObjectInstanceID: -1 + m_LastVerticalScrollValue: 0 + m_GlobalObjectId: + m_InspectorMode: 0 + m_LockTracker: + m_IsLocked: 0 + m_PreviewWindow: {fileID: 0} diff --git a/LiteNetLibSampleUnity/UserSettings/Search.settings b/LiteNetLibSampleUnity/UserSettings/Search.settings new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/LiteNetLibSampleUnity/UserSettings/Search.settings @@ -0,0 +1 @@ +{} \ No newline at end of file From 2c2bd6805d0a563a622df68b79ec16b82122fcf5 Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 11:50:05 +0200 Subject: [PATCH 004/200] fix and optimize native sockets also --- LiteNetLib/NativeSocket.cs | 48 -------------------------------- LiteNetLib/NetManager.HashSet.cs | 2 +- LiteNetLib/NetManager.Socket.cs | 41 +++++++++++++++++++++------ LiteNetLib/NetPeer.cs | 16 ++++++++--- 4 files changed, 45 insertions(+), 62 deletions(-) diff --git a/LiteNetLib/NativeSocket.cs b/LiteNetLib/NativeSocket.cs index 171f48b6..f9d7b541 100644 --- a/LiteNetLib/NativeSocket.cs +++ b/LiteNetLib/NativeSocket.cs @@ -7,54 +7,6 @@ namespace LiteNetLib { - internal class NativeEndPoint : IPEndPoint - { - public byte[] NativeAddress; - - public void CopyNativeAddress() - { - var tempAddr = new byte[NativeAddress.Length]; - Buffer.BlockCopy(NativeAddress, 0, tempAddr, 0, NativeAddress.Length); - NativeAddress = tempAddr; - } - - public void SetNetAddress(byte[] address) - { - NativeAddress = address; - short family = (short)((address[1] << 8) | address[0]); - Port =(ushort)((address[2] << 8) | address[3]); - - if ((NativeSocket.UnixMode && family == NativeSocket.AF_INET6) || (!NativeSocket.UnixMode && (AddressFamily)family == AddressFamily.InterNetworkV6)) - { - uint scope = unchecked((uint)( - (address[27] << 24) + - (address[26] << 16) + - (address[25] << 8) + - (address[24]))); -#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER - Address = new IPAddress(new ReadOnlySpan(address, 8, 16), scope); -#else - byte[] addrBuffer = new byte[16]; - Buffer.BlockCopy(address, 8, addrBuffer, 0, 16); - Address = new IPAddress(addrBuffer, scope); -#endif - } - else //IPv4 - { - long ipv4Addr = unchecked((uint)((address[4] & 0x000000FF) | - (address[5] << 8 & 0x0000FF00) | - (address[6] << 16 & 0x00FF0000) | - (address[7] << 24))); - Address = new IPAddress(ipv4Addr); - } - } - - public NativeEndPoint() : base(IPAddress.Any, 0) - { - - } - } - internal static class NativeSocket { static diff --git a/LiteNetLib/NetManager.HashSet.cs b/LiteNetLib/NetManager.HashSet.cs index 944fb2be..72181aca 100644 --- a/LiteNetLib/NetManager.HashSet.cs +++ b/LiteNetLib/NetManager.HashSet.cs @@ -205,7 +205,7 @@ private bool TryGetPeer(IPEndPoint endPoint, out NetPeer actualValue) { #if NET8_0_OR_GREATER //can be NetPeer or IPEndPoint - int hashCode = endPoint.Serialize().GetHashCode() & Lower31BitMask; + int hashCode = (UseNativeSockets ? endPoint.GetHashCode() : endPoint.Serialize().GetHashCode()) & Lower31BitMask; #else int hashCode = endPoint.GetHashCode() & Lower31BitMask; #endif diff --git a/LiteNetLib/NetManager.Socket.cs b/LiteNetLib/NetManager.Socket.cs index b3a7b56c..66b7b21e 100644 --- a/LiteNetLib/NetManager.Socket.cs +++ b/LiteNetLib/NetManager.Socket.cs @@ -129,7 +129,7 @@ private void NativeReceiveLogic() IntPtr socketHandle6 = _udpSocketv6?.Handle ?? IntPtr.Zero; byte[] addrBuffer4 = new byte[NativeSocket.IPv4AddrSize]; byte[] addrBuffer6 = new byte[NativeSocket.IPv6AddrSize]; - var tempEndPoint = new NativeEndPoint(); + var tempEndPoint = new IPEndPoint(IPAddress.Any, 0); var selectReadList = new List(2); var socketv4 = _udpSocketv4; var socketV6 = _udpSocketv6; @@ -190,11 +190,10 @@ private void NativeReceiveLogic() } } - bool NativeReceiveFrom(IntPtr s, byte[] addrBuffer) + bool NativeReceiveFrom(IntPtr s, byte[] address) { - //Reading data - int addrSize = addrBuffer.Length; - packet.Size = NativeSocket.RecvFrom(s, packet.RawData, NetConstants.MaxPacketSize, addrBuffer, ref addrSize); + int addrSize = address.Length; + packet.Size = NativeSocket.RecvFrom(s, packet.RawData, NetConstants.MaxPacketSize, address, ref addrSize); if (packet.Size == 0) return true; //socket closed or empty packet @@ -204,9 +203,34 @@ bool NativeReceiveFrom(IntPtr s, byte[] addrBuffer) return ProcessError(new SocketException((int)NativeSocket.GetSocketError())) == false; } - //All ok! //NetDebug.WriteForce($"[R]Received data from {endPoint}, result: {packet.Size}"); - tempEndPoint.SetNetAddress(addrBuffer); + //refresh temp Addr/Port + short family = (short)((address[1] << 8) | address[0]); + tempEndPoint.Port =(ushort)((address[2] << 8) | address[3]); + if ((NativeSocket.UnixMode && family == NativeSocket.AF_INET6) || (!NativeSocket.UnixMode && (AddressFamily)family == AddressFamily.InterNetworkV6)) + { + uint scope = unchecked((uint)( + (address[27] << 24) + + (address[26] << 16) + + (address[25] << 8) + + (address[24]))); +#if NETCOREAPP || NETSTANDARD2_1 || NETSTANDARD2_1_OR_GREATER + tempEndPoint.Address = new IPAddress(new ReadOnlySpan(address, 8, 16), scope); +#else + byte[] addrBuffer = new byte[16]; + Buffer.BlockCopy(address, 8, addrBuffer, 0, 16); + tempEndPoint.Address = new IPAddress(addrBuffer, scope); +#endif + } + else //IPv4 + { + long ipv4Addr = unchecked((uint)((address[4] & 0x000000FF) | + (address[5] << 8 & 0x0000FF00) | + (address[6] << 16 & 0x00FF0000) | + (address[7] << 24))); + tempEndPoint.Address = new IPAddress(ipv4Addr); + } + if (TryGetPeer(tempEndPoint, out var peer)) { //use cached native ep @@ -214,9 +238,8 @@ bool NativeReceiveFrom(IntPtr s, byte[] addrBuffer) } else { - tempEndPoint.CopyNativeAddress(); OnMessageReceived(packet, tempEndPoint); - tempEndPoint = new NativeEndPoint(); + tempEndPoint = new IPEndPoint(IPAddress.Any, 0); } packet = PoolGetPacket(NetConstants.MaxPacketSize); return true; diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index 38c10999..1852e69c 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -222,9 +222,13 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id) : bas Statistics = new NetStatistics(); NetManager = netManager; - if (NetManager.UseNativeSockets && remoteEndPoint is NativeEndPoint nep) - NativeAddress = nep.NativeAddress; _cachedSocketAddr = base.Serialize(); + if (NetManager.UseNativeSockets) + { + NativeAddress = new byte[_cachedSocketAddr.Size]; + for (int i = 0; i < _cachedSocketAddr.Size; i++) + NativeAddress[i] = _cachedSocketAddr[i]; + } #if NET8_0_OR_GREATER _cachedHashCode = NetManager.UseNativeSockets ? base.GetHashCode() : _cachedSocketAddr.GetHashCode(); #else @@ -261,8 +265,12 @@ internal void FinishEndPointChange(IPEndPoint newEndPoint) Address = newEndPoint.Address; Port = newEndPoint.Port; - if (NetManager.UseNativeSockets && newEndPoint is NativeEndPoint nep) - NativeAddress = nep.NativeAddress; + if (NetManager.UseNativeSockets) + { + NativeAddress = new byte[_cachedSocketAddr.Size]; + for (int i = 0; i < _cachedSocketAddr.Size; i++) + NativeAddress[i] = _cachedSocketAddr[i]; + } _cachedSocketAddr = base.Serialize(); #if NET8_0_OR_GREATER _cachedHashCode = NetManager.UseNativeSockets ? base.GetHashCode() : _cachedSocketAddr.GetHashCode(); From 38d962fcdaaf13964a2271d97815aa828764ab99 Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 12:13:12 +0200 Subject: [PATCH 005/200] upd --- LiteNetLibSampleUnity/Assets/LiteNetLib.dll | Bin 108544 -> 108032 bytes LiteNetLibSampleUnity/Assets/LiteNetLib.xml | 36 ++++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/LiteNetLibSampleUnity/Assets/LiteNetLib.dll b/LiteNetLibSampleUnity/Assets/LiteNetLib.dll index 7b7607d47ba80eaa40dc7e67cfa1ebabdad10a4a..039625da8c17b8fe832143e18f0ad9f9ead6b675 100644 GIT binary patch literal 108032 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 PomgOv@~hu39|isg{ZL-? literal 108544 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 - -

    - Gets peer by peer id - - id of peer - Peer if peer with id exist, otherwise null - - - - Gets peer by peer id - - id of peer - resulting peer - True if peer with id exist, otherwise false - Returns connected peers count @@ -716,6 +701,21 @@ NTP Server address. + + + Gets peer by peer id + + id of peer + Peer if peer with id exist, otherwise null + + + + Gets peer by peer id + + id of peer + resulting peer + True if peer with id exist, otherwise false + Maximum packet pool size (increase if you have tons of packets sending) @@ -811,6 +811,12 @@ Statistics of peer connection + + + IPEndPoint serialize + + SocketAddress + Returns packets count in queue for reliable channel From 786b1342414545796cc101dffa1b3f3eaee38707 Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 12:15:06 +0200 Subject: [PATCH 006/200] upd readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 48d2e622..fd26542d 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Lite reliable UDP library for .NET Standard 2.0 (Mono, .NET Core, .NET Framework * Connection statisitcs * Multicasting (for discovering hosts in local network) * Unity support +* Support for .NET8 optimized socket calls (much less gc) * Supported platforms: * Windows/Mac/Linux (.NET Framework, Mono, .NET Core, .NET Standard) * Lumin OS (Magic Leap) From 8bbcedb1dbdc6f46131bccd4628c30445492090c Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 12:21:12 +0200 Subject: [PATCH 007/200] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fd26542d..64a869bb 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,10 @@ listener.ConnectionRequestEvent += request => listener.PeerConnectedEvent += peer => { - Console.WriteLine("We got connection: {0}", peer.EndPoint); // Show peer ip - NetDataWriter writer = new NetDataWriter(); // Create writer class - writer.Put("Hello client!"); // Put some string - peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability + Console.WriteLine("We got connection: {0}", peer); // Show peer ip + NetDataWriter writer = new NetDataWriter(); // Create writer class + writer.Put("Hello client!"); // Put some string + peer.Send(writer, DeliveryMethod.ReliableOrdered); // Send with reliability }; while (!Console.KeyAvailable) From 8d9cb8386b1587d3780f2525aecde9ede9983dbf Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 20 Dec 2023 12:27:43 +0200 Subject: [PATCH 008/200] upd docs --- docs/api/LiteNetLib.ConnectionRequest.html | 68 +- docs/api/LiteNetLib.ConnectionState.html | 2 +- docs/api/LiteNetLib.DeliveryMethod.html | 2 +- docs/api/LiteNetLib.DisconnectInfo.html | 2 +- docs/api/LiteNetLib.DisconnectReason.html | 2 +- ...LiteNetLib.EventBasedNatPunchListener.html | 2 +- .../api/LiteNetLib.EventBasedNetListener.html | 2 +- .../LiteNetLib.IDeliveryEventListener.html | 2 +- docs/api/LiteNetLib.INatPunchListener.html | 2 +- docs/api/LiteNetLib.INetEventListener.html | 2 +- docs/api/LiteNetLib.INetLogger.html | 2 +- docs/api/LiteNetLib.INtpEventListener.html | 2 +- ...iteNetLib.IPeerAddressChangedListener.html | 2 +- docs/api/LiteNetLib.IPv6Mode.html | 2 +- .../LiteNetLib.InvalidPacketException.html | 2 +- docs/api/LiteNetLib.Layers.Crc32cLayer.html | 2 +- .../LiteNetLib.Layers.PacketLayerBase.html | 2 +- .../LiteNetLib.Layers.XorEncryptLayer.html | 2 +- docs/api/LiteNetLib.Layers.html | 5 +- docs/api/LiteNetLib.LocalAddrType.html | 2 +- docs/api/LiteNetLib.NatAddressType.html | 2 +- docs/api/LiteNetLib.NatPunchModule.html | 2 +- docs/api/LiteNetLib.NetConstants.html | 10 +- docs/api/LiteNetLib.NetDebug.html | 2 +- docs/api/LiteNetLib.NetLogLevel.html | 2 +- ...teNetLib.NetManager.NetPeerEnumerator.html | 49 +- docs/api/LiteNetLib.NetManager.html | 270 ++--- docs/api/LiteNetLib.NetPacketReader.html | 2 +- docs/api/LiteNetLib.NetPeer.html | 36 +- docs/api/LiteNetLib.NetStatistics.html | 8 +- docs/api/LiteNetLib.NetUtils.html | 20 +- docs/api/LiteNetLib.PooledPacket.html | 2 +- .../api/LiteNetLib.TooBigPacketException.html | 2 +- .../LiteNetLib.UnconnectedMessageType.html | 2 +- docs/api/LiteNetLib.Utils.CRC32C.html | 2 +- .../LiteNetLib.Utils.FastBitConverter.html | 2 +- .../LiteNetLib.Utils.INetSerializable.html | 2 +- ...LiteNetLib.Utils.InvalidTypeException.html | 2 +- docs/api/LiteNetLib.Utils.NetDataReader.html | 466 ++++----- docs/api/LiteNetLib.Utils.NetDataWriter.html | 208 ++-- .../LiteNetLib.Utils.NetPacketProcessor.html | 298 +++--- docs/api/LiteNetLib.Utils.NetSerializer.html | 172 ++-- .../LiteNetLib.Utils.NtpLeapIndicator.html | 2 +- docs/api/LiteNetLib.Utils.NtpMode.html | 2 +- docs/api/LiteNetLib.Utils.NtpPacket.html | 2 +- docs/api/LiteNetLib.Utils.ParseException.html | 2 +- .../LiteNetLib.Utils.PreserveAttribute.html | 2 +- docs/api/LiteNetLib.Utils.html | 11 +- docs/api/LiteNetLib.html | 14 +- docs/api/index.html | 3 +- docs/api/toc.html | 8 +- docs/api/toc.json | 2 + docs/articles/netserializerusage.html | 3 +- docs/articles/toc.html | 4 +- docs/articles/toc.json | 2 + docs/index.html | 3 +- docs/manifest.json | 13 +- docs/styles/docfx.css | 17 +- docs/styles/docfx.js | 70 +- docs/styles/docfx.vendor.min.css | 2 +- docs/styles/docfx.vendor.min.css.map | 2 +- docs/styles/docfx.vendor.min.js | 47 +- docs/styles/docfx.vendor.min.js.map | 8 +- docs/styles/main.js | 3 +- docs/styles/search-worker.min.js.map | 4 +- docs/toc.html | 4 +- docs/toc.json | 2 + docs/xrefmap.yml | 934 +++++++++--------- update_docs.bat | 2 +- 69 files changed, 1425 insertions(+), 1413 deletions(-) create mode 100644 docs/api/toc.json create mode 100644 docs/articles/toc.json create mode 100644 docs/toc.json diff --git a/docs/api/LiteNetLib.ConnectionRequest.html b/docs/api/LiteNetLib.ConnectionRequest.html index 2ac6eed4..d1a0a112 100644 --- a/docs/api/LiteNetLib.ConnectionRequest.html +++ b/docs/api/LiteNetLib.ConnectionRequest.html @@ -250,12 +250,12 @@
    Parameters
    -

    Reject(byte[], int, int, bool)

    +

    Reject(byte[])

    Declaration
    -
    public void Reject(byte[] rejectData, int start, int length, bool force)
    +
    public void Reject(byte[] rejectData)
    Parameters
    @@ -272,21 +272,6 @@
    Parameters
    - - - - - - - - - - - - - - -
    rejectData
    intstart
    intlength
    boolforce
    @@ -329,12 +314,12 @@
    Parameters
    -

    Reject(byte[])

    +

    Reject(byte[], int, int, bool)

    Declaration
    -
    public void Reject(byte[] rejectData)
    +
    public void Reject(byte[] rejectData, int start, int length, bool force)
    Parameters
    @@ -351,6 +336,21 @@
    Parameters
    + + + + + + + + + + + + + + +
    rejectData
    intstart
    intlength
    boolforce
    @@ -393,12 +393,12 @@
    Parameters
    -

    RejectForce(byte[], int, int)

    +

    RejectForce(byte[])

    Declaration
    -
    public void RejectForce(byte[] rejectData, int start, int length)
    +
    public void RejectForce(byte[] rejectData)
    Parameters
    @@ -415,27 +415,17 @@
    Parameters
    - - - - - - - - - -
    rejectData
    intstart
    intlength
    -

    RejectForce(byte[])

    +

    RejectForce(byte[], int, int)

    Declaration
    -
    public void RejectForce(byte[] rejectData)
    +
    public void RejectForce(byte[] rejectData, int start, int length)
    Parameters
    @@ -452,6 +442,16 @@
    Parameters
    + + + + + + + + + +
    rejectData
    intstart
    intlength
    @@ -465,7 +465,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.ConnectionState.html b/docs/api/LiteNetLib.ConnectionState.html index 95321853..58cf8461 100644 --- a/docs/api/LiteNetLib.ConnectionState.html +++ b/docs/api/LiteNetLib.ConnectionState.html @@ -130,7 +130,7 @@

    Fields diff --git a/docs/api/LiteNetLib.DeliveryMethod.html b/docs/api/LiteNetLib.DeliveryMethod.html index 96b966e1..26e918ca 100644 --- a/docs/api/LiteNetLib.DeliveryMethod.html +++ b/docs/api/LiteNetLib.DeliveryMethod.html @@ -131,7 +131,7 @@

    Fields diff --git a/docs/api/LiteNetLib.DisconnectInfo.html b/docs/api/LiteNetLib.DisconnectInfo.html index 045f9553..ff816c09 100644 --- a/docs/api/LiteNetLib.DisconnectInfo.html +++ b/docs/api/LiteNetLib.DisconnectInfo.html @@ -170,7 +170,7 @@

    Field Value
    diff --git a/docs/api/LiteNetLib.DisconnectReason.html b/docs/api/LiteNetLib.DisconnectReason.html index 44cb6e20..cce66c85 100644 --- a/docs/api/LiteNetLib.DisconnectReason.html +++ b/docs/api/LiteNetLib.DisconnectReason.html @@ -153,7 +153,7 @@

    Fields diff --git a/docs/api/LiteNetLib.EventBasedNatPunchListener.html b/docs/api/LiteNetLib.EventBasedNatPunchListener.html index bda25ccb..bb1556bb 100644 --- a/docs/api/LiteNetLib.EventBasedNatPunchListener.html +++ b/docs/api/LiteNetLib.EventBasedNatPunchListener.html @@ -155,7 +155,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.EventBasedNetListener.html b/docs/api/LiteNetLib.EventBasedNetListener.html index a9ce1833..52dd610f 100644 --- a/docs/api/LiteNetLib.EventBasedNetListener.html +++ b/docs/api/LiteNetLib.EventBasedNetListener.html @@ -461,7 +461,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.IDeliveryEventListener.html b/docs/api/LiteNetLib.IDeliveryEventListener.html index 5675990e..45281858 100644 --- a/docs/api/LiteNetLib.IDeliveryEventListener.html +++ b/docs/api/LiteNetLib.IDeliveryEventListener.html @@ -127,7 +127,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.INatPunchListener.html b/docs/api/LiteNetLib.INatPunchListener.html index 01ce3662..dfc3138f 100644 --- a/docs/api/LiteNetLib.INatPunchListener.html +++ b/docs/api/LiteNetLib.INatPunchListener.html @@ -168,7 +168,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.INetEventListener.html b/docs/api/LiteNetLib.INetEventListener.html index dd5989ec..3e363606 100644 --- a/docs/api/LiteNetLib.INetEventListener.html +++ b/docs/api/LiteNetLib.INetEventListener.html @@ -345,7 +345,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.INetLogger.html b/docs/api/LiteNetLib.INetLogger.html index 725cc3d8..03b29630 100644 --- a/docs/api/LiteNetLib.INetLogger.html +++ b/docs/api/LiteNetLib.INetLogger.html @@ -132,7 +132,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.INtpEventListener.html b/docs/api/LiteNetLib.INtpEventListener.html index 5df04d5d..78b5e65a 100644 --- a/docs/api/LiteNetLib.INtpEventListener.html +++ b/docs/api/LiteNetLib.INtpEventListener.html @@ -122,7 +122,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.IPeerAddressChangedListener.html b/docs/api/LiteNetLib.IPeerAddressChangedListener.html index 44c8a52d..2b3967cb 100644 --- a/docs/api/LiteNetLib.IPeerAddressChangedListener.html +++ b/docs/api/LiteNetLib.IPeerAddressChangedListener.html @@ -129,7 +129,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.IPv6Mode.html b/docs/api/LiteNetLib.IPv6Mode.html index dd9ea3be..8489a7c7 100644 --- a/docs/api/LiteNetLib.IPv6Mode.html +++ b/docs/api/LiteNetLib.IPv6Mode.html @@ -116,7 +116,7 @@

    Fields diff --git a/docs/api/LiteNetLib.InvalidPacketException.html b/docs/api/LiteNetLib.InvalidPacketException.html index 998fe148..aada234f 100644 --- a/docs/api/LiteNetLib.InvalidPacketException.html +++ b/docs/api/LiteNetLib.InvalidPacketException.html @@ -183,7 +183,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.Layers.Crc32cLayer.html b/docs/api/LiteNetLib.Layers.Crc32cLayer.html index ce524723..7c455bfd 100644 --- a/docs/api/LiteNetLib.Layers.Crc32cLayer.html +++ b/docs/api/LiteNetLib.Layers.Crc32cLayer.html @@ -201,7 +201,7 @@
    Overrides
    diff --git a/docs/api/LiteNetLib.Layers.PacketLayerBase.html b/docs/api/LiteNetLib.Layers.PacketLayerBase.html index e9e061bb..b111bbce 100644 --- a/docs/api/LiteNetLib.Layers.PacketLayerBase.html +++ b/docs/api/LiteNetLib.Layers.PacketLayerBase.html @@ -235,7 +235,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.Layers.XorEncryptLayer.html b/docs/api/LiteNetLib.Layers.XorEncryptLayer.html index 9918dfd5..5a87e07b 100644 --- a/docs/api/LiteNetLib.Layers.XorEncryptLayer.html +++ b/docs/api/LiteNetLib.Layers.XorEncryptLayer.html @@ -309,7 +309,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.Layers.html b/docs/api/LiteNetLib.Layers.html index b9224a06..2ca81449 100644 --- a/docs/api/LiteNetLib.Layers.html +++ b/docs/api/LiteNetLib.Layers.html @@ -74,7 +74,8 @@

    Names
    -

    Classes +

    +Classes

    Crc32cLayer

    @@ -94,7 +95,7 @@

    XorEncryptLaye diff --git a/docs/api/LiteNetLib.LocalAddrType.html b/docs/api/LiteNetLib.LocalAddrType.html index 7f4ccb85..78f95986 100644 --- a/docs/api/LiteNetLib.LocalAddrType.html +++ b/docs/api/LiteNetLib.LocalAddrType.html @@ -118,7 +118,7 @@

    Fields diff --git a/docs/api/LiteNetLib.NatAddressType.html b/docs/api/LiteNetLib.NatAddressType.html index 3a72ed78..ed5969fd 100644 --- a/docs/api/LiteNetLib.NatAddressType.html +++ b/docs/api/LiteNetLib.NatAddressType.html @@ -112,7 +112,7 @@

    Fields diff --git a/docs/api/LiteNetLib.NatPunchModule.html b/docs/api/LiteNetLib.NatPunchModule.html index d6f0eb40..185ac2f0 100644 --- a/docs/api/LiteNetLib.NatPunchModule.html +++ b/docs/api/LiteNetLib.NatPunchModule.html @@ -304,7 +304,7 @@

    Parameters
    diff --git a/docs/api/LiteNetLib.NetConstants.html b/docs/api/LiteNetLib.NetConstants.html index 67a78ace..075c478b 100644 --- a/docs/api/LiteNetLib.NetConstants.html +++ b/docs/api/LiteNetLib.NetConstants.html @@ -139,12 +139,12 @@
    Field Value
    -

    FragmentedHeaderTotalSize

    +

    FragmentHeaderSize

    Declaration
    -
    public const int FragmentedHeaderTotalSize = 10
    +
    public const int FragmentHeaderSize = 6
    Field Value
    @@ -163,12 +163,12 @@
    Field Value
    -

    FragmentHeaderSize

    +

    FragmentedHeaderTotalSize

    Declaration
    -
    public const int FragmentHeaderSize = 6
    +
    public const int FragmentedHeaderTotalSize = 10
    Field Value
    @@ -388,7 +388,7 @@
    Field Value
    diff --git a/docs/api/LiteNetLib.NetDebug.html b/docs/api/LiteNetLib.NetDebug.html index e89dfa84..9cef6dac 100644 --- a/docs/api/LiteNetLib.NetDebug.html +++ b/docs/api/LiteNetLib.NetDebug.html @@ -125,7 +125,7 @@
    Field Value
    diff --git a/docs/api/LiteNetLib.NetLogLevel.html b/docs/api/LiteNetLib.NetLogLevel.html index db1fd024..61298f6c 100644 --- a/docs/api/LiteNetLib.NetLogLevel.html +++ b/docs/api/LiteNetLib.NetLogLevel.html @@ -120,7 +120,7 @@

    Fields diff --git a/docs/api/LiteNetLib.NetManager.NetPeerEnumerator.html b/docs/api/LiteNetLib.NetManager.NetPeerEnumerator.html index fcb2c4d9..729887a2 100644 --- a/docs/api/LiteNetLib.NetManager.NetPeerEnumerator.html +++ b/docs/api/LiteNetLib.NetManager.NetPeerEnumerator.html @@ -122,7 +122,8 @@

    Properties

    Current

    -
    +

    Gets the element in the collection at the current position of the enumerator.

    +
    Declaration
    @@ -139,7 +140,8 @@
    Property Value
    - +
    NetPeer

    The element in the collection at the current position of the enumerator.

    +
    @@ -160,7 +162,8 @@

    Declaration

    MoveNext()

    -
    +

    Advances the enumerator to the next element of the collection.

    +
    Declaration
    @@ -177,7 +180,24 @@
    Returns
    bool - +

    true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.

    + + + + +
    Exceptions
    + + + + + + + + + + +
    TypeCondition
    InvalidOperationException

    The collection was modified after the enumerator was created.

    +
    @@ -185,12 +205,29 @@
    Returns

    Reset()

    -
    +

    Sets the enumerator to its initial position, which is before the first element in the collection.

    +
    Declaration
    public void Reset()
    +
    Exceptions
    + + + + + + + + + + + + + +
    TypeCondition
    InvalidOperationException

    The collection was modified after the enumerator was created.

    +

    Implements

    IEnumerator<T> @@ -212,7 +249,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.NetManager.html b/docs/api/LiteNetLib.NetManager.html index ffd90695..27c74cd4 100644 --- a/docs/api/LiteNetLib.NetManager.html +++ b/docs/api/LiteNetLib.NetManager.html @@ -1458,13 +1458,13 @@
    Parameters
    -

    CreateNtpRequest(string, int)

    -

    Create the requests for NTP server

    +

    CreateNtpRequest(string)

    +

    Create the requests for NTP server (default port)

    Declaration
    -
    public void CreateNtpRequest(string ntpServerAddress, int port)
    +
    public void CreateNtpRequest(string ntpServerAddress)
    Parameters
    @@ -1480,12 +1480,6 @@
    Parameters
    - - - - - @@ -1493,13 +1487,13 @@
    Parameters
    -

    CreateNtpRequest(string)

    -

    Create the requests for NTP server (default port)

    +

    CreateNtpRequest(string, int)

    +

    Create the requests for NTP server

    Declaration
    -
    public void CreateNtpRequest(string ntpServerAddress)
    +
    public void CreateNtpRequest(string ntpServerAddress, int port)
    Parameters
    string ntpServerAddress

    NTP Server address.

    -
    intport

    port

    @@ -1515,6 +1509,12 @@
    Parameters
    + + + + + @@ -1574,13 +1574,13 @@
    Parameters
    -

    DisconnectPeer(NetPeer, NetDataWriter)

    -

    Disconnect peer from server and send additional data (Size must be less or equal MTU - 8)

    +

    DisconnectPeer(NetPeer)

    +

    Disconnect peer from server

    Declaration
    -
    public void DisconnectPeer(NetPeer peer, NetDataWriter writer)
    +
    public void DisconnectPeer(NetPeer peer)
    Parameters
    string ntpServerAddress

    NTP Server address.

    +
    intport

    port

    @@ -1596,12 +1596,6 @@
    Parameters
    - - - - - @@ -1609,13 +1603,13 @@
    Parameters
    -

    DisconnectPeer(NetPeer, byte[], int, int)

    +

    DisconnectPeer(NetPeer, NetDataWriter)

    Disconnect peer from server and send additional data (Size must be less or equal MTU - 8)

    Declaration
    -
    public void DisconnectPeer(NetPeer peer, byte[] data, int start, int count)
    +
    public void DisconnectPeer(NetPeer peer, NetDataWriter writer)
    Parameters
    NetPeer peer

    peer to disconnect

    -
    NetDataWriterwriter

    additional data

    @@ -1634,21 +1628,9 @@
    Parameters
    - - + + - - - - - - - - - - @@ -1691,13 +1673,13 @@
    Parameters
    -

    DisconnectPeer(NetPeer)

    -

    Disconnect peer from server

    +

    DisconnectPeer(NetPeer, byte[], int, int)

    +

    Disconnect peer from server and send additional data (Size must be less or equal MTU - 8)

    Declaration
    -
    public void DisconnectPeer(NetPeer peer)
    +
    public void DisconnectPeer(NetPeer peer, byte[] data, int start, int count)
    Parameters
    byte[]dataNetDataWriterwriter

    additional data

    -
    intstart

    data start

    -
    intcount

    data length

    @@ -1713,6 +1695,24 @@
    Parameters
    + + + + + + + + + + + + + + + @@ -1987,12 +1987,12 @@
    Returns
    -

    SendBroadcast(byte[], int, int, int)

    +

    SendBroadcast(byte[], int)

    Declaration
    -
    public bool SendBroadcast(byte[] data, int start, int length, int port)
    +
    public bool SendBroadcast(byte[] data, int port)
    Parameters
    NetPeer peer

    peer to disconnect

    +
    byte[]data

    additional data

    +
    intstart

    data start

    +
    intcount

    data length

    @@ -2009,16 +2009,6 @@
    Parameters
    - - - - - - - - - - @@ -2044,12 +2034,12 @@
    Returns
    -

    SendBroadcast(byte[], int)

    +

    SendBroadcast(byte[], int, int, int)

    Declaration
    -
    public bool SendBroadcast(byte[] data, int port)
    +
    public bool SendBroadcast(byte[] data, int start, int length, int port)
    Parameters
    data
    intstart
    intlength
    int port
    @@ -2066,6 +2056,16 @@
    Parameters
    + + + + + + + + + + @@ -2091,13 +2091,13 @@
    Returns
    -

    SendToAll(NetDataWriter, DeliveryMethod, NetPeer)

    +

    SendToAll(NetDataWriter, DeliveryMethod)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(NetDataWriter writer, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(NetDataWriter writer, DeliveryMethod options)
    Parameters
    data
    intstart
    intlength
    int port
    @@ -2119,12 +2119,6 @@
    Parameters
    - - - - - @@ -2132,13 +2126,13 @@
    Parameters
    -

    SendToAll(NetDataWriter, DeliveryMethod)

    +

    SendToAll(NetDataWriter, DeliveryMethod, NetPeer)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(NetDataWriter writer, DeliveryMethod options)
    +
    public void SendToAll(NetDataWriter writer, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2160,6 +2154,12 @@
    Parameters
    + + + + + @@ -2167,13 +2167,13 @@
    Parameters
    -

    SendToAll(NetDataWriter, byte, DeliveryMethod, NetPeer)

    +

    SendToAll(NetDataWriter, byte, DeliveryMethod)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2201,12 +2201,6 @@
    Parameters
    - - - - - @@ -2214,13 +2208,13 @@
    Parameters
    -

    SendToAll(NetDataWriter, byte, DeliveryMethod)

    +

    SendToAll(NetDataWriter, byte, DeliveryMethod, NetPeer)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options)
    +
    public void SendToAll(NetDataWriter writer, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2248,6 +2242,12 @@
    Parameters
    + + + + + @@ -2255,13 +2255,13 @@
    Parameters
    -

    SendToAll(byte[], DeliveryMethod, NetPeer)

    +

    SendToAll(byte[], DeliveryMethod)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(byte[] data, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(byte[] data, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2283,12 +2283,6 @@
    Parameters
    - - - - - @@ -2296,13 +2290,13 @@
    Parameters
    -

    SendToAll(byte[], DeliveryMethod)

    +

    SendToAll(byte[], DeliveryMethod, NetPeer)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(byte[] data, DeliveryMethod options)
    +
    public void SendToAll(byte[] data, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2324,6 +2318,12 @@
    Parameters
    + + + + + @@ -2331,13 +2331,13 @@
    Parameters
    -

    SendToAll(byte[], byte, DeliveryMethod, NetPeer)

    +

    SendToAll(byte[], byte, DeliveryMethod)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2365,12 +2365,6 @@
    Parameters
    - - - - - @@ -2378,13 +2372,13 @@
    Parameters
    -

    SendToAll(byte[], byte, DeliveryMethod)

    +

    SendToAll(byte[], byte, DeliveryMethod, NetPeer)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options)
    +
    public void SendToAll(byte[] data, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2412,6 +2406,12 @@
    Parameters
    + + + + + @@ -2419,13 +2419,13 @@
    Parameters
    -

    SendToAll(byte[], int, int, DeliveryMethod, NetPeer)

    +

    SendToAll(byte[], int, int, DeliveryMethod)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(byte[] data, int start, int length, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(byte[] data, int start, int length, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2459,12 +2459,6 @@
    Parameters
    - - - - - @@ -2472,13 +2466,13 @@
    Parameters
    -

    SendToAll(byte[], int, int, DeliveryMethod)

    +

    SendToAll(byte[], int, int, DeliveryMethod, NetPeer)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(byte[] data, int start, int length, DeliveryMethod options)
    +
    public void SendToAll(byte[] data, int start, int length, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2512,6 +2506,12 @@
    Parameters
    + + + + + @@ -2519,13 +2519,13 @@
    Parameters
    -

    SendToAll(byte[], int, int, byte, DeliveryMethod, NetPeer)

    +

    SendToAll(byte[], int, int, byte, DeliveryMethod)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2565,12 +2565,6 @@
    Parameters
    - - - - - @@ -2578,13 +2572,13 @@
    Parameters
    -

    SendToAll(byte[], int, int, byte, DeliveryMethod)

    +

    SendToAll(byte[], int, int, byte, DeliveryMethod, NetPeer)

    Send data to all connected peers

    Declaration
    -
    public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options)
    +
    public void SendToAll(byte[] data, int start, int length, byte channelNumber, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2624,6 +2618,12 @@
    Parameters
    + + + + + @@ -2631,13 +2631,13 @@
    Parameters
    -

    SendToAll(ReadOnlySpan<byte>, DeliveryMethod, NetPeer)

    +

    SendToAll(ReadOnlySpan<byte>, DeliveryMethod)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options, NetPeer excludePeer)
    +
    public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -2659,12 +2659,6 @@
    Parameters
    - - - - - @@ -2672,13 +2666,13 @@
    Parameters
    -

    SendToAll(ReadOnlySpan<byte>, DeliveryMethod)

    +

    SendToAll(ReadOnlySpan<byte>, DeliveryMethod, NetPeer)

    Send data to all connected peers (channel - 0)

    Declaration
    -
    public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options)
    +
    public void SendToAll(ReadOnlySpan<byte> data, DeliveryMethod options, NetPeer excludePeer)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    -
    NetPeerexcludePeer

    Excluded peer

    @@ -2700,6 +2694,12 @@
    Parameters
    + + + + + @@ -3048,13 +3048,13 @@
    Returns
    -

    Start(IPAddress, IPAddress, int, bool)

    +

    Start(IPAddress, IPAddress, int)

    Start logic thread and listening on selected port

    Declaration
    -
    public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode)
    +
    public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port)
    Parameters
    DeliveryMethod options

    Send options (reliable, unreliable, etc.)

    +
    NetPeerexcludePeer

    Excluded peer

    @@ -3082,12 +3082,6 @@
    Parameters
    - - - - - @@ -3110,13 +3104,13 @@
    Returns
    -

    Start(IPAddress, IPAddress, int)

    +

    Start(IPAddress, IPAddress, int, bool)

    Start logic thread and listening on selected port

    Declaration
    -
    public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port)
    +
    public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode)
    Parameters
    int port

    port to listen

    -
    boolmanualMode

    mode of library

    @@ -3144,6 +3138,12 @@
    Parameters
    + + + + + @@ -3504,7 +3504,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.NetPacketReader.html b/docs/api/LiteNetLib.NetPacketReader.html index 00602912..87cf9b13 100644 --- a/docs/api/LiteNetLib.NetPacketReader.html +++ b/docs/api/LiteNetLib.NetPacketReader.html @@ -404,7 +404,7 @@
    Declaration
    diff --git a/docs/api/LiteNetLib.NetPeer.html b/docs/api/LiteNetLib.NetPeer.html index 40b7f38e..5539d422 100644 --- a/docs/api/LiteNetLib.NetPeer.html +++ b/docs/api/LiteNetLib.NetPeer.html @@ -522,12 +522,12 @@
    Parameters
    -

    Disconnect(byte[], int, int)

    +

    Disconnect(byte[])

    Declaration
    -
    public void Disconnect(byte[] data, int start, int count)
    +
    public void Disconnect(byte[] data)
    Parameters
    int port

    port to listen

    +
    boolmanualMode

    mode of library

    @@ -544,27 +544,17 @@
    Parameters
    - - - - - - - - - -
    data
    intstart
    intcount
    -

    Disconnect(byte[])

    +

    Disconnect(byte[], int, int)

    Declaration
    -
    public void Disconnect(byte[] data)
    +
    public void Disconnect(byte[] data, int start, int count)
    Parameters
    @@ -581,13 +571,24 @@
    Parameters
    + + + + + + + + + +
    data
    intstart
    intcount

    GetHashCode()

    -
    +

    Returns a hash value for a IPEndPoint instance.

    +
    Declaration
    @@ -604,7 +605,8 @@
    Returns
    int - +

    An integer hash value.

    + @@ -1517,7 +1519,7 @@
    Overrides
    diff --git a/docs/api/LiteNetLib.NetStatistics.html b/docs/api/LiteNetLib.NetStatistics.html index 467a448d..3283b0bf 100644 --- a/docs/api/LiteNetLib.NetStatistics.html +++ b/docs/api/LiteNetLib.NetStatistics.html @@ -365,7 +365,8 @@
    Declaration

    ToString()

    -
    +

    Returns a string that represents the current object.

    +
    Declaration
    @@ -382,7 +383,8 @@
    Returns
    string - +

    A string that represents the current object.

    + @@ -399,7 +401,7 @@
    Overrides
    diff --git a/docs/api/LiteNetLib.NetUtils.html b/docs/api/LiteNetLib.NetUtils.html index a982d647..acb748f6 100644 --- a/docs/api/LiteNetLib.NetUtils.html +++ b/docs/api/LiteNetLib.NetUtils.html @@ -264,12 +264,12 @@
    Returns
    -

    ResolveAddress(string, AddressFamily)

    +

    ResolveAddress(string)

    Declaration
    -
    public static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily)
    +
    public static IPAddress ResolveAddress(string hostStr)
    Parameters
    @@ -286,11 +286,6 @@
    Parameters
    - - - - -
    hostStr
    AddressFamilyaddressFamily
    Returns
    @@ -311,12 +306,12 @@
    Returns
    -

    ResolveAddress(string)

    +

    ResolveAddress(string, AddressFamily)

    Declaration
    -
    public static IPAddress ResolveAddress(string hostStr)
    +
    public static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily)
    Parameters
    @@ -333,6 +328,11 @@
    Parameters
    + + + + +
    hostStr
    AddressFamilyaddressFamily
    Returns
    @@ -361,7 +361,7 @@
    Returns
    diff --git a/docs/api/LiteNetLib.PooledPacket.html b/docs/api/LiteNetLib.PooledPacket.html index abe69e6e..23467e19 100644 --- a/docs/api/LiteNetLib.PooledPacket.html +++ b/docs/api/LiteNetLib.PooledPacket.html @@ -172,7 +172,7 @@
    Property Value
    diff --git a/docs/api/LiteNetLib.TooBigPacketException.html b/docs/api/LiteNetLib.TooBigPacketException.html index e693f28b..48c940da 100644 --- a/docs/api/LiteNetLib.TooBigPacketException.html +++ b/docs/api/LiteNetLib.TooBigPacketException.html @@ -183,7 +183,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.UnconnectedMessageType.html b/docs/api/LiteNetLib.UnconnectedMessageType.html index f1d4a9c8..65865180 100644 --- a/docs/api/LiteNetLib.UnconnectedMessageType.html +++ b/docs/api/LiteNetLib.UnconnectedMessageType.html @@ -113,7 +113,7 @@

    Fields diff --git a/docs/api/LiteNetLib.Utils.CRC32C.html b/docs/api/LiteNetLib.Utils.CRC32C.html index bf01f7aa..86671d66 100644 --- a/docs/api/LiteNetLib.Utils.CRC32C.html +++ b/docs/api/LiteNetLib.Utils.CRC32C.html @@ -182,7 +182,7 @@

    Returns
    diff --git a/docs/api/LiteNetLib.Utils.FastBitConverter.html b/docs/api/LiteNetLib.Utils.FastBitConverter.html index 13a8c291..7745f3d6 100644 --- a/docs/api/LiteNetLib.Utils.FastBitConverter.html +++ b/docs/api/LiteNetLib.Utils.FastBitConverter.html @@ -151,7 +151,7 @@
    Type Parameters
    diff --git a/docs/api/LiteNetLib.Utils.INetSerializable.html b/docs/api/LiteNetLib.Utils.INetSerializable.html index b01448e3..5c3316db 100644 --- a/docs/api/LiteNetLib.Utils.INetSerializable.html +++ b/docs/api/LiteNetLib.Utils.INetSerializable.html @@ -148,7 +148,7 @@
    Parameters
    diff --git a/docs/api/LiteNetLib.Utils.InvalidTypeException.html b/docs/api/LiteNetLib.Utils.InvalidTypeException.html index e7b08274..0f00ff1d 100644 --- a/docs/api/LiteNetLib.Utils.InvalidTypeException.html +++ b/docs/api/LiteNetLib.Utils.InvalidTypeException.html @@ -182,7 +182,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.Utils.NetDataReader.html b/docs/api/LiteNetLib.Utils.NetDataReader.html index 75e15722..253c3d14 100644 --- a/docs/api/LiteNetLib.Utils.NetDataReader.html +++ b/docs/api/LiteNetLib.Utils.NetDataReader.html @@ -129,12 +129,12 @@
    Parameters
    -

    NetDataReader(byte[], int, int)

    +

    NetDataReader(byte[])

    Declaration
    -
    public NetDataReader(byte[] source, int offset, int maxSize)
    +
    public NetDataReader(byte[] source)
    Parameters
    @@ -151,27 +151,17 @@
    Parameters
    - - - - - - - - - -
    source
    intoffset
    intmaxSize
    -

    NetDataReader(byte[])

    +

    NetDataReader(byte[], int, int)

    Declaration
    -
    public NetDataReader(byte[] source)
    +
    public NetDataReader(byte[] source, int offset, int maxSize)
    Parameters
    @@ -188,6 +178,16 @@
    Parameters
    + + + + + + + + + +
    source
    intoffset
    intmaxSize

    Fields @@ -751,12 +751,12 @@

    Parameters
    -

    Get(out string, int)

    +

    Get(out string)

    Declaration
    -
    public void Get(out string result, int maxLength)
    +
    public void Get(out string result)
    Parameters
    @@ -773,22 +773,17 @@
    Parameters
    - - - - -
    result
    intmaxLength
    -

    Get(out string)

    +

    Get(out string, int)

    Declaration
    -
    public void Get(out string result)
    +
    public void Get(out string result, int maxLength)
    Parameters
    @@ -805,6 +800,11 @@
    Parameters
    + + + + +
    result
    intmaxLength
    @@ -890,192 +890,6 @@
    Parameters
    - -

    Get<T>()

    -
    -
    -
    Declaration
    -
    -
    public T Get<T>() where T : struct, INetSerializable
    -
    -
    Returns
    - - - - - - - - - - - - - -
    TypeDescription
    T
    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    - - - -

    Get<T>(out T, Func<T>)

    -
    -
    -
    Declaration
    -
    -
    public void Get<T>(out T result, Func<T> constructor) where T : class, INetSerializable
    -
    -
    Parameters
    - - - - - - - - - - - - - - - - - - - - -
    TypeNameDescription
    Tresult
    Func<T>constructor
    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    - - - -

    Get<T>(out T)

    -
    -
    -
    Declaration
    -
    -
    public void Get<T>(out T result) where T : struct, INetSerializable
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    Tresult
    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    - - - -

    Get<T>(Func<T>)

    -
    -
    -
    Declaration
    -
    -
    public T Get<T>(Func<T> constructor) where T : class, INetSerializable
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    Func<T>constructor
    -
    Returns
    - - - - - - - - - - - - - -
    TypeDescription
    T
    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    - -

    GetArray<T>(ushort)

    @@ -1209,12 +1023,12 @@
    Returns
    -

    GetBytes(byte[], int, int)

    +

    GetBytes(byte[], int)

    Declaration
    -
    public void GetBytes(byte[] destination, int start, int count)
    +
    public void GetBytes(byte[] destination, int count)
    Parameters
    @@ -1231,11 +1045,6 @@
    Parameters
    - - - - - @@ -1246,12 +1055,12 @@
    Parameters
    -

    GetBytes(byte[], int)

    +

    GetBytes(byte[], int, int)

    Declaration
    -
    public void GetBytes(byte[] destination, int count)
    +
    public void GetBytes(byte[] destination, int start, int count)
    Parameters
    destination
    intstart
    int count
    @@ -1268,6 +1077,11 @@
    Parameters
    + + + + + @@ -2057,6 +1871,192 @@
    Returns
    destination
    intstart
    int count
    + +

    Get<T>()

    +
    +
    +
    Declaration
    +
    +
    public T Get<T>() where T : struct, INetSerializable
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T
    + + + +

    Get<T>(Func<T>)

    +
    +
    +
    Declaration
    +
    +
    public T Get<T>(Func<T> constructor) where T : class, INetSerializable
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Func<T>constructor
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T
    + + + +

    Get<T>(out T)

    +
    +
    +
    Declaration
    +
    +
    public void Get<T>(out T result) where T : struct, INetSerializable
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tresult
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T
    + + + +

    Get<T>(out T, Func<T>)

    +
    +
    +
    Declaration
    +
    +
    public void Get<T>(out T result, Func<T> constructor) where T : class, INetSerializable
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tresult
    Func<T>constructor
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T
    + +

    PeekBool()

    @@ -2480,12 +2480,12 @@
    Parameters
    -

    SetSource(byte[], int, int)

    +

    SetSource(byte[])

    Declaration
    -
    public void SetSource(byte[] source, int offset, int maxSize)
    +
    public void SetSource(byte[] source)
    Parameters
    @@ -2502,27 +2502,17 @@
    Parameters
    - - - - - - - - - -
    source
    intoffset
    intmaxSize
    -

    SetSource(byte[])

    +

    SetSource(byte[], int, int)

    Declaration
    -
    public void SetSource(byte[] source)
    +
    public void SetSource(byte[] source, int offset, int maxSize)
    Parameters
    @@ -2539,6 +2529,16 @@
    Parameters
    + + + + + + + + + +
    source
    intoffset
    intmaxSize
    @@ -3209,7 +3209,7 @@
    Returns
    diff --git a/docs/api/LiteNetLib.Utils.NetDataWriter.html b/docs/api/LiteNetLib.Utils.NetDataWriter.html index ad9fd94a..93719d42 100644 --- a/docs/api/LiteNetLib.Utils.NetDataWriter.html +++ b/docs/api/LiteNetLib.Utils.NetDataWriter.html @@ -101,12 +101,12 @@
    Declaration
    -

    NetDataWriter(bool, int)

    +

    NetDataWriter(bool)

    Declaration
    -
    public NetDataWriter(bool autoResize, int initialSize)
    +
    public NetDataWriter(bool autoResize)
    Parameters
    @@ -123,22 +123,17 @@
    Parameters
    - - - - -
    autoResize
    intinitialSize
    -

    NetDataWriter(bool)

    +

    NetDataWriter(bool, int)

    Declaration
    -
    public NetDataWriter(bool autoResize)
    +
    public NetDataWriter(bool autoResize, int initialSize)
    Parameters
    @@ -155,18 +150,23 @@
    Parameters
    + + + + +
    autoResize
    intinitialSize

    Fields

    -

    _data

    +

    StringBufferMaxLength

    Declaration
    -
    protected byte[] _data
    +
    public const int StringBufferMaxLength = 65535
    Field Value
    @@ -178,19 +178,19 @@
    Field Value
    - +
    byte[]int
    -

    _position

    +

    _data

    Declaration
    -
    protected int _position
    +
    protected byte[] _data
    Field Value
    @@ -202,19 +202,19 @@
    Field Value
    - +
    intbyte[]
    -

    StringBufferMaxLength

    +

    _position

    Declaration
    -
    public const int StringBufferMaxLength = 65535
    +
    protected int _position
    Field Value
    @@ -591,12 +591,12 @@
    Parameters
    -

    Put(byte[], int, int)

    +

    Put(byte[])

    Declaration
    -
    public void Put(byte[] data, int offset, int length)
    +
    public void Put(byte[] data)
    Parameters
    @@ -613,27 +613,17 @@
    Parameters
    - - - - - - - - - -
    data
    intoffset
    intlength
    -

    Put(byte[])

    +

    Put(byte[], int, int)

    Declaration
    -
    public void Put(byte[] data)
    +
    public void Put(byte[] data, int offset, int length)
    Parameters
    @@ -650,6 +640,16 @@
    Parameters
    + + + + + + + + + +
    data
    intoffset
    intlength
    @@ -871,13 +871,12 @@
    Parameters
    -

    Put(string, int)

    -

    Note that "maxLength" only limits the number of characters in a string, not its size in bytes.

    -
    +

    Put(string)

    +
    Declaration
    -
    public void Put(string value, int maxLength)
    +
    public void Put(string value)
    Parameters
    @@ -894,22 +893,18 @@
    Parameters
    - - - - -
    value
    intmaxLength
    -

    Put(string)

    -
    +

    Put(string, int)

    +

    Note that "maxLength" only limits the number of characters in a string, not its size in bytes.

    +
    Declaration
    -
    public void Put(string value)
    +
    public void Put(string value, int maxLength)
    Parameters
    @@ -926,6 +921,11 @@
    Parameters
    + + + + +
    value
    intmaxLength
    @@ -1011,48 +1011,6 @@
    Parameters
    - -

    Put<T>(T)

    -
    -
    -
    Declaration
    -
    -
    public void Put<T>(T obj) where T : INetSerializable
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    Tobj
    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    - -

    PutArray(Array, int)

    @@ -1248,12 +1206,12 @@
    Parameters
    -

    PutArray(string[], int)

    +

    PutArray(string[])

    Declaration
    -
    public void PutArray(string[] value, int strMaxLength)
    +
    public void PutArray(string[] value)
    Parameters
    @@ -1270,22 +1228,17 @@
    Parameters
    - - - - -
    value
    intstrMaxLength
    -

    PutArray(string[])

    +

    PutArray(string[], int)

    Declaration
    -
    public void PutArray(string[] value)
    +
    public void PutArray(string[] value, int strMaxLength)
    Parameters
    @@ -1302,6 +1255,11 @@
    Parameters
    + + + + +
    value
    intstrMaxLength
    @@ -1387,6 +1345,33 @@
    Parameters
    + +

    PutBytesWithLength(byte[])

    +
    +
    +
    Declaration
    +
    +
    public void PutBytesWithLength(byte[] data)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]data
    + +

    PutBytesWithLength(byte[], int, ushort)

    @@ -1424,13 +1409,13 @@
    Parameters
    - -

    PutBytesWithLength(byte[])

    + +

    PutSBytesWithLength(sbyte[])

    Declaration
    -
    public void PutBytesWithLength(byte[] data)
    +
    public void PutSBytesWithLength(sbyte[] data)
    Parameters
    @@ -1443,7 +1428,7 @@
    Parameters
    - + @@ -1488,13 +1473,13 @@
    Parameters
    byte[]sbyte[] data
    - -

    PutSBytesWithLength(sbyte[])

    + +

    Put<T>(T)

    Declaration
    -
    public void PutSBytesWithLength(sbyte[] data)
    +
    public void Put<T>(T obj) where T : INetSerializable
    Parameters
    @@ -1507,8 +1492,23 @@
    Parameters
    - - + + + + + +
    sbyte[]dataTobj
    +
    Type Parameters
    + + + + + + + + + + @@ -1633,7 +1633,7 @@
    Returns
    diff --git a/docs/api/LiteNetLib.Utils.NetPacketProcessor.html b/docs/api/LiteNetLib.Utils.NetPacketProcessor.html index d15f536d..c49f91fc 100644 --- a/docs/api/LiteNetLib.Utils.NetPacketProcessor.html +++ b/docs/api/LiteNetLib.Utils.NetPacketProcessor.html @@ -212,13 +212,13 @@
    Type Parameters
    -

    ReadAllPackets(NetDataReader, object)

    +

    ReadAllPackets(NetDataReader)

    Reads all available data from NetDataReader and calls OnReceive delegates

    Declaration
    -
    public void ReadAllPackets(NetDataReader reader, object userData)
    +
    public void ReadAllPackets(NetDataReader reader)
    Parameters
    NameDescription
    T
    @@ -234,28 +234,6 @@
    Parameters
    - - - - - - - -
    NetDataReader reader

    NetDataReader with packets data

    -
    objectuserData

    Argument that passed to OnReceivedEvent

    -
    -
    Exceptions
    - - - - - - - - - - - @@ -263,13 +241,13 @@
    Exceptions
    -

    ReadAllPackets(NetDataReader)

    +

    ReadAllPackets(NetDataReader, object)

    Reads all available data from NetDataReader and calls OnReceive delegates

    Declaration
    -
    public void ReadAllPackets(NetDataReader reader)
    +
    public void ReadAllPackets(NetDataReader reader, object userData)
    Parameters
    TypeCondition
    ParseException

    Malformed packet

    @@ -285,6 +263,28 @@
    Parameters
    + + + + + + + +
    NetDataReader reader

    NetDataReader with packets data

    +
    objectuserData

    Argument that passed to OnReceivedEvent

    +
    +
    Exceptions
    + + + + + + + + + + + @@ -292,13 +292,13 @@
    Parameters
    -

    ReadPacket(NetDataReader, object)

    +

    ReadPacket(NetDataReader)

    Reads one packet from NetDataReader and calls OnReceive delegate

    Declaration
    -
    public void ReadPacket(NetDataReader reader, object userData)
    +
    public void ReadPacket(NetDataReader reader)
    Parameters
    TypeCondition
    ParseException

    Malformed packet

    @@ -314,12 +314,6 @@
    Parameters
    - - - - - @@ -343,13 +337,13 @@
    Exceptions
    -

    ReadPacket(NetDataReader)

    +

    ReadPacket(NetDataReader, object)

    Reads one packet from NetDataReader and calls OnReceive delegate

    Declaration
    -
    public void ReadPacket(NetDataReader reader)
    +
    public void ReadPacket(NetDataReader reader, object userData)
    Parameters
    NetDataReader reader

    NetDataReader with packet

    -
    objectuserData

    Argument that passed to OnReceivedEvent

    @@ -365,6 +359,12 @@
    Parameters
    + + + + + @@ -549,14 +549,13 @@
    Type Parameters
    NetDataReader reader

    NetDataReader with packet

    +
    objectuserData

    Argument that passed to OnReceivedEvent

    - -

    Subscribe<T>(Action<T>, Func<T>)

    -

    Register and subscribe to packet receive event

    -
    + +

    SubscribeNetSerializable<T>(Action<T>)

    +
    Declaration
    -
    public void Subscribe<T>(Action<T> onReceive, Func<T> packetConstructor) where T : class, new()
    +
    public void SubscribeNetSerializable<T>(Action<T> onReceive) where T : INetSerializable, new()
    Parameters
    @@ -571,14 +570,7 @@
    Parameters
    - - - - - - +
    Action<T> onReceive

    event that will be called when packet deserialized with ReadPacket method

    -
    Func<T>packetConstructor

    Method that constructs packet instead of slow Activator.CreateInstance

    -
    @@ -597,32 +589,15 @@
    Type Parameters
    -
    Exceptions
    - - - - - - - - - - - - - -
    TypeCondition
    InvalidTypeException

    T's fields are not supported, or it has no fields

    -
    - -

    Subscribe<T, TUserData>(Action<T, TUserData>, Func<T>)

    -

    Register and subscribe to packet receive event (with userData)

    -
    + +

    SubscribeNetSerializable<T>(Action<T>, Func<T>)

    +
    Declaration
    -
    public void Subscribe<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : class, new()
    +
    public void SubscribeNetSerializable<T>(Action<T> onReceive, Func<T> packetConstructor) where T : INetSerializable
    Parameters
    @@ -635,16 +610,14 @@
    Parameters
    - + - + - +
    Action<T, TUserData>Action<T> onReceive

    event that will be called when packet deserialized with ReadPacket method

    -
    Func<T> packetConstructor

    Method that constructs packet instead of slow Activator.CreateInstance

    -
    @@ -661,37 +634,17 @@
    Type Parameters
    T - - TUserData - - - - -
    Exceptions
    - - - - - - - - - - - -
    TypeCondition
    InvalidTypeException

    T's fields are not supported, or it has no fields

    -
    -

    SubscribeNetSerializable<T>(Action<T>, Func<T>)

    +

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>)

    Declaration
    -
    public void SubscribeNetSerializable<T>(Action<T> onReceive, Func<T> packetConstructor) where T : INetSerializable
    +
    public void SubscribeNetSerializable<T, TUserData>(Action<T, TUserData> onReceive) where T : INetSerializable, new()
    Parameters
    @@ -704,15 +657,10 @@
    Parameters
    - + - - - - -
    Action<T>Action<T, TUserData> onReceive
    Func<T>packetConstructor
    Type Parameters
    @@ -728,17 +676,21 @@
    Type Parameters
    T + + TUserData + + -

    SubscribeNetSerializable<T>(Action<T>)

    +

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>, Func<T>)

    Declaration
    -
    public void SubscribeNetSerializable<T>(Action<T> onReceive) where T : INetSerializable, new()
    +
    public void SubscribeNetSerializable<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : INetSerializable
    Parameters
    @@ -751,10 +703,15 @@
    Parameters
    - + + + + + +
    Action<T>Action<T, TUserData> onReceive
    Func<T>packetConstructor
    Type Parameters
    @@ -770,17 +727,23 @@
    Type Parameters
    T + + TUserData + + - -

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>, Func<T>)

    -
    + +

    SubscribeReusable<T>(Action<T>)

    +

    Register and subscribe to packet receive event +This method will overwrite last received packet class on receive (less garbage)

    +
    Declaration
    -
    public void SubscribeNetSerializable<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : INetSerializable
    +
    public void SubscribeReusable<T>(Action<T> onReceive) where T : class, new()
    Parameters
    @@ -793,14 +756,10 @@
    Parameters
    - + - - - - - - +
    Action<T, TUserData>Action<T> onReceive
    Func<T>packetConstructor

    event that will be called when packet deserialized with ReadPacket method

    +
    @@ -817,21 +776,35 @@
    Type Parameters
    T + + +
    Exceptions
    + + - - + + + + + + + +
    TUserDataTypeCondition
    InvalidTypeException

    T's fields are not supported, or it has no fields

    +
    - -

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>)

    -
    + +

    SubscribeReusable<T, TUserData>(Action<T, TUserData>)

    +

    Register and subscribe to packet receive event +This method will overwrite last received packet class on receive (less garbage)

    +
    Declaration
    -
    public void SubscribeNetSerializable<T, TUserData>(Action<T, TUserData> onReceive) where T : INetSerializable, new()
    +
    public void SubscribeReusable<T, TUserData>(Action<T, TUserData> onReceive) where T : class, new()
    Parameters
    @@ -846,7 +819,8 @@
    Parameters
    - +
    Action<T, TUserData> onReceive

    event that will be called when packet deserialized with ReadPacket method

    +
    @@ -869,17 +843,32 @@
    Type Parameters
    +
    Exceptions
    + + + + + + + + + + + + + +
    TypeCondition
    InvalidTypeException

    T's fields are not supported, or it has no fields

    +
    - -

    SubscribeReusable<T>(Action<T>)

    -

    Register and subscribe to packet receive event -This method will overwrite last received packet class on receive (less garbage)

    + +

    Subscribe<T>(Action<T>, Func<T>)

    +

    Register and subscribe to packet receive event

    Declaration
    -
    public void SubscribeReusable<T>(Action<T> onReceive) where T : class, new()
    +
    public void Subscribe<T>(Action<T> onReceive, Func<T> packetConstructor) where T : class, new()
    Parameters
    @@ -895,6 +884,12 @@
    Parameters
    + + + + + @@ -932,15 +927,14 @@
    Exceptions
    Action<T> onReceive

    event that will be called when packet deserialized with ReadPacket method

    +
    Func<T>packetConstructor

    Method that constructs packet instead of slow Activator.CreateInstance

    - -

    SubscribeReusable<T, TUserData>(Action<T, TUserData>)

    -

    Register and subscribe to packet receive event -This method will overwrite last received packet class on receive (less garbage)

    + +

    Subscribe<T, TUserData>(Action<T, TUserData>, Func<T>)

    +

    Register and subscribe to packet receive event (with userData)

    Declaration
    -
    public void SubscribeReusable<T, TUserData>(Action<T, TUserData> onReceive) where T : class, new()
    +
    public void Subscribe<T, TUserData>(Action<T, TUserData> onReceive, Func<T> packetConstructor) where T : class, new()
    Parameters
    @@ -956,6 +950,12 @@
    Parameters
    + + + + + @@ -997,13 +997,13 @@
    Exceptions
    Action<T, TUserData> onReceive

    event that will be called when packet deserialized with ReadPacket method

    +
    Func<T>packetConstructor

    Method that constructs packet instead of slow Activator.CreateInstance

    - -

    Write<T>(NetDataWriter, T)

    + +

    WriteHash<T>(NetDataWriter)

    Declaration
    -
    public void Write<T>(NetDataWriter writer, T packet) where T : class, new()
    +
    protected virtual void WriteHash<T>(NetDataWriter writer)
    Parameters
    @@ -1020,11 +1020,6 @@
    Parameters
    - - - - -
    writer
    Tpacket
    Type Parameters
    @@ -1044,13 +1039,13 @@
    Type Parameters
    - -

    WriteHash<T>(NetDataWriter)

    + +

    WriteNetSerializable<T>(NetDataWriter, ref T)

    Declaration
    -
    protected virtual void WriteHash<T>(NetDataWriter writer)
    +
    public void WriteNetSerializable<T>(NetDataWriter writer, ref T packet) where T : INetSerializable
    Parameters
    @@ -1067,6 +1062,11 @@
    Parameters
    + + + + +
    writer
    Tpacket
    Type Parameters
    @@ -1086,13 +1086,13 @@
    Type Parameters
    - -

    WriteNetSerializable<T>(NetDataWriter, ref T)

    + +

    Write<T>(NetDataWriter, T)

    Declaration
    -
    public void WriteNetSerializable<T>(NetDataWriter writer, ref T packet) where T : INetSerializable
    +
    public void Write<T>(NetDataWriter writer, T packet) where T : class, new()
    Parameters
    @@ -1142,7 +1142,7 @@
    Type Parameters
    diff --git a/docs/api/LiteNetLib.Utils.NetSerializer.html b/docs/api/LiteNetLib.Utils.NetSerializer.html index 15d99753..a39f26e5 100644 --- a/docs/api/LiteNetLib.Utils.NetSerializer.html +++ b/docs/api/LiteNetLib.Utils.NetSerializer.html @@ -130,13 +130,13 @@

    Methods -

    Deserialize<T>(NetDataReader, T)

    -

    Reads packet with known type (non alloc variant)

    +

    Deserialize<T>(NetDataReader)

    +

    Reads packet with known type

    Declaration
    -
    public bool Deserialize<T>(NetDataReader reader, T target) where T : class, new()
    +
    public T Deserialize<T>(NetDataReader reader) where T : class, new()
    Parameters
    @@ -152,12 +152,6 @@
    Parameters
    - - - - - @@ -172,8 +166,8 @@
    Returns
    - - + @@ -212,13 +206,13 @@
    Exceptions
    -

    Deserialize<T>(NetDataReader)

    -

    Reads packet with known type

    +

    Deserialize<T>(NetDataReader, T)

    +

    Reads packet with known type (non alloc variant)

    Declaration
    -
    public T Deserialize<T>(NetDataReader reader) where T : class, new()
    +
    public bool Deserialize<T>(NetDataReader reader, T target) where T : class, new()
    Parameters
    NetDataReader reader

    NetDataReader with packet

    -
    Ttarget

    Deserialization target

    bool

    Returns true if packet in reader is matched type

    +
    T

    Returns packet if packet in reader is matched type

    @@ -236,65 +230,30 @@
    Parameters
    - -

    NetDataReader with packet

    -
    Returns
    - - - - - - - - - +
    TypeDescription
    T

    Returns packet if packet in reader is matched type

    +
    target

    Deserialization target

    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    -
    Exceptions
    +
    Returns
    - + - - +
    TypeConditionDescription
    InvalidTypeException

    T's fields are not supported, or it has no fields

    +
    bool

    Returns true if packet in reader is matched type

    - - - -

    Register<T>()

    -
    -
    -
    Declaration
    -
    -
    public void Register<T>()
    -
    Type Parameters
    @@ -450,64 +409,45 @@
    Type Parameters
    - -

    Serialize<T>(T)

    -

    Serialize object to byte array

    -
    + +

    Register<T>()

    +
    Declaration
    -
    public byte[] Serialize<T>(T obj) where T : class, new()
    +
    public void Register<T>()
    -
    Parameters
    +
    Type Parameters
    - - - - + +
    Type Name Description
    Tobj

    Object to serialize

    -
    T
    -
    Returns
    +
    Exceptions
    - + - - +
    TypeDescriptionCondition
    byte[]

    byte array with serialized data

    +
    InvalidTypeException

    T's fields are not supported, or it has no fields

    -
    Type Parameters
    - - - - - - - - - - - - - -
    NameDescription
    T
    @@ -575,6 +515,66 @@
    Exceptions
    + + +

    Serialize<T>(T)

    +

    Serialize object to byte array

    +
    +
    +
    Declaration
    +
    +
    public byte[] Serialize<T>(T obj) where T : class, new()
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tobj

    Object to serialize

    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    byte[]

    byte array with serialized data

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T
    +
    @@ -585,7 +585,7 @@
    Exceptions
    diff --git a/docs/api/LiteNetLib.Utils.NtpLeapIndicator.html b/docs/api/LiteNetLib.Utils.NtpLeapIndicator.html index a41b662d..c797e09d 100644 --- a/docs/api/LiteNetLib.Utils.NtpLeapIndicator.html +++ b/docs/api/LiteNetLib.Utils.NtpLeapIndicator.html @@ -129,7 +129,7 @@
    See Also
    diff --git a/docs/api/LiteNetLib.Utils.NtpMode.html b/docs/api/LiteNetLib.Utils.NtpMode.html index 7a203a2c..e1e29604 100644 --- a/docs/api/LiteNetLib.Utils.NtpMode.html +++ b/docs/api/LiteNetLib.Utils.NtpMode.html @@ -119,7 +119,7 @@
    See Also
    diff --git a/docs/api/LiteNetLib.Utils.NtpPacket.html b/docs/api/LiteNetLib.Utils.NtpPacket.html index 313c36cf..fa85dae3 100644 --- a/docs/api/LiteNetLib.Utils.NtpPacket.html +++ b/docs/api/LiteNetLib.Utils.NtpPacket.html @@ -731,7 +731,7 @@
    Returns
    diff --git a/docs/api/LiteNetLib.Utils.ParseException.html b/docs/api/LiteNetLib.Utils.ParseException.html index f3659548..eb121abc 100644 --- a/docs/api/LiteNetLib.Utils.ParseException.html +++ b/docs/api/LiteNetLib.Utils.ParseException.html @@ -177,7 +177,7 @@

    Implements

    diff --git a/docs/api/LiteNetLib.Utils.PreserveAttribute.html b/docs/api/LiteNetLib.Utils.PreserveAttribute.html index 8a61f6c0..7dc49e53 100644 --- a/docs/api/LiteNetLib.Utils.PreserveAttribute.html +++ b/docs/api/LiteNetLib.Utils.PreserveAttribute.html @@ -214,7 +214,7 @@
    Syntax
    diff --git a/docs/api/LiteNetLib.Utils.html b/docs/api/LiteNetLib.Utils.html index d7951740..fadfa6fa 100644 --- a/docs/api/LiteNetLib.Utils.html +++ b/docs/api/LiteNetLib.Utils.html @@ -74,7 +74,8 @@

    Namespa
    -

    Classes +

    +Classes

    CRC32C

    @@ -98,11 +99,13 @@

    ParseExceptionPreserveAttribute

    PreserveAttribute prevents byte code stripping from removing a class, method, field, or property.

    -

    Interfaces +

    +Interfaces

    INetSerializable

    -

    Enums +

    +Enums

    NtpLeapIndicator

    Represents leap second warning from the server that instructs the client to add or remove leap second.

    @@ -122,7 +125,7 @@

    NtpMode

    diff --git a/docs/api/LiteNetLib.html b/docs/api/LiteNetLib.html index 9e5bc4e8..e947bfd3 100644 --- a/docs/api/LiteNetLib.html +++ b/docs/api/LiteNetLib.html @@ -74,7 +74,8 @@

    Namespace LiteNetLi
    -

    Classes +

    +Classes

    ConnectionRequest

    @@ -109,7 +110,8 @@

    NetUtils

    TooBigPacketException

    -

    Structs +

    +Structs

    DisconnectInfo

    Additional information about disconnection

    @@ -118,7 +120,8 @@

    NetManag

    PooledPacket

    -

    Interfaces +

    +Interfaces

    IDeliveryEventListener

    @@ -133,7 +136,8 @@

    INtpEventListener

    IPeerAddressChangedListener

    -

    Enums +

    +Enums

    ConnectionState

    Peer connection state

    @@ -166,7 +170,7 @@

    UnconnectedMes diff --git a/docs/api/index.html b/docs/api/index.html index 85e708e6..3f2ccb15 100644 --- a/docs/api/index.html +++ b/docs/api/index.html @@ -68,6 +68,7 @@

    LiteNetLib

    +
    @@ -78,7 +79,7 @@

    LiteNetLib

    diff --git a/docs/api/toc.html b/docs/api/toc.html index 12210740..17d678aa 100644 --- a/docs/api/toc.html +++ b/docs/api/toc.html @@ -5,7 +5,7 @@
    - +
    - \ No newline at end of file + diff --git a/docs/api/toc.json b/docs/api/toc.json new file mode 100644 index 00000000..9c70d1f3 --- /dev/null +++ b/docs/api/toc.json @@ -0,0 +1,2 @@ + +{"items":[{"name":"LiteNetLib","href":"LiteNetLib.html","topicHref":"LiteNetLib.html","topicUid":"LiteNetLib","items":[{"name":"ConnectionRequest","href":"LiteNetLib.ConnectionRequest.html","topicHref":"LiteNetLib.ConnectionRequest.html","topicUid":"LiteNetLib.ConnectionRequest"},{"name":"ConnectionState","href":"LiteNetLib.ConnectionState.html","topicHref":"LiteNetLib.ConnectionState.html","topicUid":"LiteNetLib.ConnectionState"},{"name":"DeliveryMethod","href":"LiteNetLib.DeliveryMethod.html","topicHref":"LiteNetLib.DeliveryMethod.html","topicUid":"LiteNetLib.DeliveryMethod"},{"name":"DisconnectInfo","href":"LiteNetLib.DisconnectInfo.html","topicHref":"LiteNetLib.DisconnectInfo.html","topicUid":"LiteNetLib.DisconnectInfo"},{"name":"DisconnectReason","href":"LiteNetLib.DisconnectReason.html","topicHref":"LiteNetLib.DisconnectReason.html","topicUid":"LiteNetLib.DisconnectReason"},{"name":"EventBasedNatPunchListener","href":"LiteNetLib.EventBasedNatPunchListener.html","topicHref":"LiteNetLib.EventBasedNatPunchListener.html","topicUid":"LiteNetLib.EventBasedNatPunchListener"},{"name":"EventBasedNetListener","href":"LiteNetLib.EventBasedNetListener.html","topicHref":"LiteNetLib.EventBasedNetListener.html","topicUid":"LiteNetLib.EventBasedNetListener"},{"name":"IDeliveryEventListener","href":"LiteNetLib.IDeliveryEventListener.html","topicHref":"LiteNetLib.IDeliveryEventListener.html","topicUid":"LiteNetLib.IDeliveryEventListener"},{"name":"INatPunchListener","href":"LiteNetLib.INatPunchListener.html","topicHref":"LiteNetLib.INatPunchListener.html","topicUid":"LiteNetLib.INatPunchListener"},{"name":"INetEventListener","href":"LiteNetLib.INetEventListener.html","topicHref":"LiteNetLib.INetEventListener.html","topicUid":"LiteNetLib.INetEventListener"},{"name":"INetLogger","href":"LiteNetLib.INetLogger.html","topicHref":"LiteNetLib.INetLogger.html","topicUid":"LiteNetLib.INetLogger"},{"name":"INtpEventListener","href":"LiteNetLib.INtpEventListener.html","topicHref":"LiteNetLib.INtpEventListener.html","topicUid":"LiteNetLib.INtpEventListener"},{"name":"IPeerAddressChangedListener","href":"LiteNetLib.IPeerAddressChangedListener.html","topicHref":"LiteNetLib.IPeerAddressChangedListener.html","topicUid":"LiteNetLib.IPeerAddressChangedListener"},{"name":"InvalidPacketException","href":"LiteNetLib.InvalidPacketException.html","topicHref":"LiteNetLib.InvalidPacketException.html","topicUid":"LiteNetLib.InvalidPacketException"},{"name":"LocalAddrType","href":"LiteNetLib.LocalAddrType.html","topicHref":"LiteNetLib.LocalAddrType.html","topicUid":"LiteNetLib.LocalAddrType"},{"name":"NatAddressType","href":"LiteNetLib.NatAddressType.html","topicHref":"LiteNetLib.NatAddressType.html","topicUid":"LiteNetLib.NatAddressType"},{"name":"NatPunchModule","href":"LiteNetLib.NatPunchModule.html","topicHref":"LiteNetLib.NatPunchModule.html","topicUid":"LiteNetLib.NatPunchModule"},{"name":"NetConstants","href":"LiteNetLib.NetConstants.html","topicHref":"LiteNetLib.NetConstants.html","topicUid":"LiteNetLib.NetConstants"},{"name":"NetDebug","href":"LiteNetLib.NetDebug.html","topicHref":"LiteNetLib.NetDebug.html","topicUid":"LiteNetLib.NetDebug"},{"name":"NetLogLevel","href":"LiteNetLib.NetLogLevel.html","topicHref":"LiteNetLib.NetLogLevel.html","topicUid":"LiteNetLib.NetLogLevel"},{"name":"NetManager","href":"LiteNetLib.NetManager.html","topicHref":"LiteNetLib.NetManager.html","topicUid":"LiteNetLib.NetManager"},{"name":"NetManager.NetPeerEnumerator","href":"LiteNetLib.NetManager.NetPeerEnumerator.html","topicHref":"LiteNetLib.NetManager.NetPeerEnumerator.html","topicUid":"LiteNetLib.NetManager.NetPeerEnumerator"},{"name":"NetPacketReader","href":"LiteNetLib.NetPacketReader.html","topicHref":"LiteNetLib.NetPacketReader.html","topicUid":"LiteNetLib.NetPacketReader"},{"name":"NetPeer","href":"LiteNetLib.NetPeer.html","topicHref":"LiteNetLib.NetPeer.html","topicUid":"LiteNetLib.NetPeer"},{"name":"NetStatistics","href":"LiteNetLib.NetStatistics.html","topicHref":"LiteNetLib.NetStatistics.html","topicUid":"LiteNetLib.NetStatistics"},{"name":"NetUtils","href":"LiteNetLib.NetUtils.html","topicHref":"LiteNetLib.NetUtils.html","topicUid":"LiteNetLib.NetUtils"},{"name":"PooledPacket","href":"LiteNetLib.PooledPacket.html","topicHref":"LiteNetLib.PooledPacket.html","topicUid":"LiteNetLib.PooledPacket"},{"name":"TooBigPacketException","href":"LiteNetLib.TooBigPacketException.html","topicHref":"LiteNetLib.TooBigPacketException.html","topicUid":"LiteNetLib.TooBigPacketException"},{"name":"UnconnectedMessageType","href":"LiteNetLib.UnconnectedMessageType.html","topicHref":"LiteNetLib.UnconnectedMessageType.html","topicUid":"LiteNetLib.UnconnectedMessageType"}]},{"name":"LiteNetLib.Layers","href":"LiteNetLib.Layers.html","topicHref":"LiteNetLib.Layers.html","topicUid":"LiteNetLib.Layers","items":[{"name":"Crc32cLayer","href":"LiteNetLib.Layers.Crc32cLayer.html","topicHref":"LiteNetLib.Layers.Crc32cLayer.html","topicUid":"LiteNetLib.Layers.Crc32cLayer"},{"name":"PacketLayerBase","href":"LiteNetLib.Layers.PacketLayerBase.html","topicHref":"LiteNetLib.Layers.PacketLayerBase.html","topicUid":"LiteNetLib.Layers.PacketLayerBase"},{"name":"XorEncryptLayer","href":"LiteNetLib.Layers.XorEncryptLayer.html","topicHref":"LiteNetLib.Layers.XorEncryptLayer.html","topicUid":"LiteNetLib.Layers.XorEncryptLayer"}]},{"name":"LiteNetLib.Utils","href":"LiteNetLib.Utils.html","topicHref":"LiteNetLib.Utils.html","topicUid":"LiteNetLib.Utils","items":[{"name":"CRC32C","href":"LiteNetLib.Utils.CRC32C.html","topicHref":"LiteNetLib.Utils.CRC32C.html","topicUid":"LiteNetLib.Utils.CRC32C"},{"name":"FastBitConverter","href":"LiteNetLib.Utils.FastBitConverter.html","topicHref":"LiteNetLib.Utils.FastBitConverter.html","topicUid":"LiteNetLib.Utils.FastBitConverter"},{"name":"INetSerializable","href":"LiteNetLib.Utils.INetSerializable.html","topicHref":"LiteNetLib.Utils.INetSerializable.html","topicUid":"LiteNetLib.Utils.INetSerializable"},{"name":"InvalidTypeException","href":"LiteNetLib.Utils.InvalidTypeException.html","topicHref":"LiteNetLib.Utils.InvalidTypeException.html","topicUid":"LiteNetLib.Utils.InvalidTypeException"},{"name":"NetDataReader","href":"LiteNetLib.Utils.NetDataReader.html","topicHref":"LiteNetLib.Utils.NetDataReader.html","topicUid":"LiteNetLib.Utils.NetDataReader"},{"name":"NetDataWriter","href":"LiteNetLib.Utils.NetDataWriter.html","topicHref":"LiteNetLib.Utils.NetDataWriter.html","topicUid":"LiteNetLib.Utils.NetDataWriter"},{"name":"NetPacketProcessor","href":"LiteNetLib.Utils.NetPacketProcessor.html","topicHref":"LiteNetLib.Utils.NetPacketProcessor.html","topicUid":"LiteNetLib.Utils.NetPacketProcessor"},{"name":"NetSerializer","href":"LiteNetLib.Utils.NetSerializer.html","topicHref":"LiteNetLib.Utils.NetSerializer.html","topicUid":"LiteNetLib.Utils.NetSerializer"},{"name":"NtpLeapIndicator","href":"LiteNetLib.Utils.NtpLeapIndicator.html","topicHref":"LiteNetLib.Utils.NtpLeapIndicator.html","topicUid":"LiteNetLib.Utils.NtpLeapIndicator"},{"name":"NtpMode","href":"LiteNetLib.Utils.NtpMode.html","topicHref":"LiteNetLib.Utils.NtpMode.html","topicUid":"LiteNetLib.Utils.NtpMode"},{"name":"NtpPacket","href":"LiteNetLib.Utils.NtpPacket.html","topicHref":"LiteNetLib.Utils.NtpPacket.html","topicUid":"LiteNetLib.Utils.NtpPacket"},{"name":"ParseException","href":"LiteNetLib.Utils.ParseException.html","topicHref":"LiteNetLib.Utils.ParseException.html","topicUid":"LiteNetLib.Utils.ParseException"},{"name":"PreserveAttribute","href":"LiteNetLib.Utils.PreserveAttribute.html","topicHref":"LiteNetLib.Utils.PreserveAttribute.html","topicUid":"LiteNetLib.Utils.PreserveAttribute"}]}],"memberLayout":"SamePage"} diff --git a/docs/articles/netserializerusage.html b/docs/articles/netserializerusage.html index aaae5e4f..77bc445d 100644 --- a/docs/articles/netserializerusage.html +++ b/docs/articles/netserializerusage.html @@ -227,6 +227,7 @@

    Mini FAQ

    Q: NetPacketProcessor throws "Undefined packet in NetDataReader" but all packets are registered.
    A: This can happen when packet definitions resides in different namespaces. Check that registered packet classes/structs are in the same namespace on both ends. To avoid this error altogether, use shared code/-assembly for packets.

    + @@ -237,7 +238,7 @@

    Mini FAQ

    diff --git a/docs/articles/toc.html b/docs/articles/toc.html index db355290..8de463ca 100644 --- a/docs/articles/toc.html +++ b/docs/articles/toc.html @@ -5,7 +5,7 @@
    - +
    @@ -19,4 +19,4 @@
    - \ No newline at end of file + diff --git a/docs/articles/toc.json b/docs/articles/toc.json new file mode 100644 index 00000000..a67e5ac5 --- /dev/null +++ b/docs/articles/toc.json @@ -0,0 +1,2 @@ + +{"items":[{"name":"NetSerializer usage","href":"netserializerusage.html","topicHref":"netserializerusage.html"}]} diff --git a/docs/index.html b/docs/index.html index ea6e98b2..fba02201 100644 --- a/docs/index.html +++ b/docs/index.html @@ -246,6 +246,7 @@

    NetManager settings description

    + @@ -256,7 +257,7 @@

    NetManager settings description

    diff --git a/docs/manifest.json b/docs/manifest.json index a0c5141c..ac7fb948 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -1,6 +1,5 @@ { - "homepages": [], - "source_base_path": "e:/Projects/LiteNetLib/docfx_project", + "source_base_path": "E:/Projects/LiteNetLib/docfx_project", "xrefmap": "xrefmap.yml", "files": [ { @@ -509,6 +508,9 @@ "output": { ".html": { "relative_path": "api/toc.html" + }, + ".json": { + "relative_path": "api/toc.json" } }, "version": "" @@ -529,6 +531,9 @@ "output": { ".html": { "relative_path": "articles/toc.html" + }, + ".json": { + "relative_path": "articles/toc.json" } }, "version": "" @@ -549,12 +554,14 @@ "output": { ".html": { "relative_path": "toc.html" + }, + ".json": { + "relative_path": "toc.json" } }, "version": "" } ], - "version_info": {}, "groups": [ { "xrefmap": "xrefmap.yml" diff --git a/docs/styles/docfx.css b/docs/styles/docfx.css index 34ee31bb..7d80d139 100644 --- a/docs/styles/docfx.css +++ b/docs/styles/docfx.css @@ -1,4 +1,7 @@ -/* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. */ +/** + * Licensed to the .NET Foundation under one or more agreements. + * The .NET Foundation licenses this file to you under the MIT license. + */ html, body { font-family: 'Segoe UI', Tahoma, Helvetica, sans-serif; @@ -108,10 +111,6 @@ span.languagekeyword{ font-weight: bold; } -svg:hover path { - fill: #ffffff; -} - .hljs { display: inline; background-color: inherit; @@ -826,7 +825,7 @@ footer { .toc .level1 > li { display: block; } - + .toc .level1 > li:after { display: none; } @@ -1034,3 +1033,9 @@ div.embeddedvideo iframe { font-weight: bold; margin-top: 2em; } + +@media print { + @page { + margin: .4in; + } +} diff --git a/docs/styles/docfx.js b/docs/styles/docfx.js index 16bafe8c..5bd62e28 100644 --- a/docs/styles/docfx.js +++ b/docs/styles/docfx.js @@ -1,4 +1,5 @@ -// Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. $(function () { var active = 'active'; var expanded = 'in'; @@ -127,13 +128,10 @@ $(function () { return; } try { - var worker = new Worker(relHref + 'styles/search-worker.min.js'); - if (!worker && !window.worker) { - localSearch(); - } else { - webWorkerSearch(); + if(!window.Worker){ + return; } - + webWorkerSearch(); renderSearchBox(); highlightKeywords(); addSearchEvent(); @@ -163,50 +161,14 @@ $(function () { } } - // Search factory - function localSearch() { - console.log("using local search"); - var lunrIndex = lunr(function () { - this.ref('href'); - this.field('title', { boost: 50 }); - this.field('keywords', { boost: 20 }); - }); - lunr.tokenizer.seperator = /[\s\-\.]+/; - var searchData = {}; - var searchDataRequest = new XMLHttpRequest(); - - var indexPath = relHref + "index.json"; - if (indexPath) { - searchDataRequest.open('GET', indexPath); - searchDataRequest.onload = function () { - if (this.status != 200) { - return; - } - searchData = JSON.parse(this.responseText); - for (var prop in searchData) { - if (searchData.hasOwnProperty(prop)) { - lunrIndex.add(searchData[prop]); - } - } - } - searchDataRequest.send(); - } - - $("body").bind("queryReady", function () { - var hits = lunrIndex.search(query); - var results = []; - hits.forEach(function (hit) { - var item = searchData[hit.ref]; - results.push({ 'href': item.href, 'title': item.title, 'keywords': item.keywords }); - }); - handleSearchResults(results); - }); - } - function webWorkerSearch() { - console.log("using Web Worker"); var indexReady = $.Deferred(); + var worker = new Worker(relHref + 'styles/search-worker.min.js'); + worker.onerror = function (oEvent) { + console.error('Error occurred at search-worker. message: ' + oEvent.message); + } + worker.onmessage = function (oEvent) { switch (oEvent.data.e) { case 'index-ready': @@ -251,7 +213,7 @@ $(function () { $('#search-query').keyup(function () { query = $(this).val(); - if (query.length < 3) { + if (query === '') { flipContents("show"); } else { flipContents("hide"); @@ -306,7 +268,7 @@ $(function () { pagination.removeData("twbs-pagination"); if (hits.length === 0) { $('#search-results>.sr-items').html('

    No results found

    '); - } else { + } else { pagination.twbsPagination({ first: pagination.data('first'), prev: pagination.data('prev'), @@ -354,7 +316,7 @@ $(function () { renderBreadcrumb(); showSearch(); } - + function showSearch() { if ($('#search-results').length !== 0) { $('#search').show(); @@ -443,7 +405,7 @@ $(function () { function registerTocEvents() { var tocFilterInput = $('#toc_filter_input'); var tocFilterClearButton = $('#toc_filter_clear'); - + $('.toc .nav > li > .expand-stub').click(function (e) { $(e.target).parent().toggleClass(expanded); }); @@ -477,7 +439,7 @@ $(function () { parent.removeClass(show); parent.removeClass(filtered); }) - + // Get leaf nodes $('#toc li>a').filter(function (i, e) { return $(e).siblings().length === 0 @@ -518,7 +480,7 @@ $(function () { return false; } }); - + // toc filter clear button tocFilterClearButton.hide(); tocFilterClearButton.on("click", function(e){ diff --git a/docs/styles/docfx.vendor.min.css b/docs/styles/docfx.vendor.min.css index b809553e..0faa137a 100644 --- a/docs/styles/docfx.vendor.min.css +++ b/docs/styles/docfx.vendor.min.css @@ -1,4 +1,4 @@ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*,*:before,*:after{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:Glyphicons Halflings;src:url(./glyphicons-halflings-regular-PIHUWCJO.eot);src:url(./glyphicons-halflings-regular-PIHUWCJO.eot?#iefix) format("embedded-opentype"),url(./glyphicons-halflings-regular-W4DYDFZM.woff2) format("woff2"),url(./glyphicons-halflings-regular-JOUF32XT.woff) format("woff"),url(./glyphicons-halflings-regular-ACNUA6UY.ttf) format("truetype"),url(./glyphicons-halflings-regular-QXYEM3FU.svg#glyphicons_halflingsregular) format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:Glyphicons Halflings;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"*"}.glyphicon-plus:before{content:"+"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\a5"}.glyphicon-jpy:before{content:"\a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width: 768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width: 768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:"\2014\a0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eeeeee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:""}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:"\a0\2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Courier New,monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px #00000040}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 768px){.container{width:750px}}@media (min-width: 992px){.container{width:970px}}@media (min-width: 1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width: 768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width: 992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width: 1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width: 767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \ ;line-height:normal}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px #00000013,0 0 8px #66afe999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio: 0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month]{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \ ;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px #00000013,0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px #00000013,0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px #00000013,0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width: 768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width: 768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width: 768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width: 768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px #00000020}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \ ;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px #0000002d}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;inset:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid \ }.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width: 768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px #00000020}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child:not(:first-child){border-radius:0 0 4px 4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=radio],[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width: 768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width: 768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width: 768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width: 768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width: 768px){.navbar{border-radius:4px}}@media (min-width: 768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px #ffffff1a;-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width: 768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width: 480px) and (orientation: landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}@media (min-width: 768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width: 768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width: 768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width: 768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width: 768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width: 767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width: 768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin:8px -15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px #ffffff1a,0 1px #ffffff1a}@media (min-width: 768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width: 767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width: 768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width: 768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width: 768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width: 767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width: 767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width: 768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px #0000001a}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px #00000026;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px #0000000d}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px #0000000d}.well blockquote{border-color:#ddd;border-color:#00000026}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;inset:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px #00000080;outline:0}.modal-backdrop{position:fixed;inset:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px #00000080}.modal-sm{width:300px}}@media (min-width: 992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px #0003}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:#00000040;border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:#00000040;border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:#00000040}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:#00000040}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0,0,0);transform:translateZ(0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:#0000;filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80000000",endColorstr="#00000000",GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#00000000",endColorstr="#80000000",GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \ ;background-color:#0000;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width: 768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width: 767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width: 767px){.visible-xs-block{display:block!important}}@media (max-width: 767px){.visible-xs-inline{display:inline!important}}@media (max-width: 767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-block{display:block!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-inline{display:inline!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-block{display:block!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-inline{display:inline!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width: 1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width: 1200px){.visible-lg-block{display:block!important}}@media (min-width: 1200px){.visible-lg-inline{display:inline!important}}@media (min-width: 1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width: 767px){.hidden-xs{display:none!important}}@media (min-width: 768px) and (max-width: 991px){.hidden-sm{display:none!important}}@media (min-width: 992px) and (max-width: 1199px){.hidden-md{display:none!important}}@media (min-width: 1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0} +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;-moz-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*,*:before,*:after{color:#000!important;text-shadow:none!important;background:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}@font-face{font-family:Glyphicons Halflings;src:url("./glyphicons-halflings-regular-PIHUWCJO.eot");src:url("./glyphicons-halflings-regular-PIHUWCJO.eot?#iefix") format("embedded-opentype"),url("./glyphicons-halflings-regular-W4DYDFZM.woff2") format("woff2"),url("./glyphicons-halflings-regular-JOUF32XT.woff") format("woff"),url("./glyphicons-halflings-regular-ACNUA6UY.ttf") format("truetype"),url("./glyphicons-halflings-regular-QXYEM3FU.svg#glyphicons_halflingsregular") format("svg")}.glyphicon{position:relative;top:1px;display:inline-block;font-family:Glyphicons Halflings;font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"*"}.glyphicon-plus:before{content:"+"}.glyphicon-euro:before,.glyphicon-eur:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.glyphicon-cd:before{content:"\e201"}.glyphicon-save-file:before{content:"\e202"}.glyphicon-open-file:before{content:"\e203"}.glyphicon-level-up:before{content:"\e204"}.glyphicon-copy:before{content:"\e205"}.glyphicon-paste:before{content:"\e206"}.glyphicon-alert:before{content:"\e209"}.glyphicon-equalizer:before{content:"\e210"}.glyphicon-king:before{content:"\e211"}.glyphicon-queen:before{content:"\e212"}.glyphicon-pawn:before{content:"\e213"}.glyphicon-bishop:before{content:"\e214"}.glyphicon-knight:before{content:"\e215"}.glyphicon-baby-formula:before{content:"\e216"}.glyphicon-tent:before{content:"\26fa"}.glyphicon-blackboard:before{content:"\e218"}.glyphicon-bed:before{content:"\e219"}.glyphicon-apple:before{content:"\f8ff"}.glyphicon-erase:before{content:"\e221"}.glyphicon-hourglass:before{content:"\231b"}.glyphicon-lamp:before{content:"\e223"}.glyphicon-duplicate:before{content:"\e224"}.glyphicon-piggy-bank:before{content:"\e225"}.glyphicon-scissors:before{content:"\e226"}.glyphicon-bitcoin:before{content:"\e227"}.glyphicon-btc:before{content:"\e227"}.glyphicon-xbt:before{content:"\e227"}.glyphicon-yen:before{content:"\a5"}.glyphicon-jpy:before{content:"\a5"}.glyphicon-ruble:before{content:"\20bd"}.glyphicon-rub:before{content:"\20bd"}.glyphicon-scale:before{content:"\e230"}.glyphicon-ice-lolly:before{content:"\e231"}.glyphicon-ice-lolly-tasted:before{content:"\e232"}.glyphicon-education:before{content:"\e233"}.glyphicon-option-horizontal:before{content:"\e234"}.glyphicon-option-vertical:before{content:"\e235"}.glyphicon-menu-hamburger:before{content:"\e236"}.glyphicon-modal-window:before{content:"\e237"}.glyphicon-oil:before{content:"\e238"}.glyphicon-grain:before{content:"\e239"}.glyphicon-sunglasses:before{content:"\e240"}.glyphicon-text-size:before{content:"\e241"}.glyphicon-text-color:before{content:"\e242"}.glyphicon-text-background:before{content:"\e243"}.glyphicon-object-align-top:before{content:"\e244"}.glyphicon-object-align-bottom:before{content:"\e245"}.glyphicon-object-align-horizontal:before{content:"\e246"}.glyphicon-object-align-left:before{content:"\e247"}.glyphicon-object-align-vertical:before{content:"\e248"}.glyphicon-object-align-right:before{content:"\e249"}.glyphicon-triangle-right:before{content:"\e250"}.glyphicon-triangle-left:before{content:"\e251"}.glyphicon-triangle-bottom:before{content:"\e252"}.glyphicon-triangle-top:before{content:"\e253"}.glyphicon-console:before{content:"\e254"}.glyphicon-superscript:before{content:"\e255"}.glyphicon-subscript:before{content:"\e256"}.glyphicon-menu-left:before{content:"\e257"}.glyphicon-menu-right:before{content:"\e258"}.glyphicon-menu-down:before{content:"\e259"}.glyphicon-menu-up:before{content:"\e260"}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#337ab7;text-decoration:none}a:hover,a:focus{color:#23527c;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive,.thumbnail>img,.thumbnail a>img,.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#777}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width: 768px){.lead{font-size:21px}}small,.small{font-size:85%}mark,.mark{padding:.2em;background-color:#fcf8e3}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-uppercase{text-transform:uppercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}.text-primary{color:#337ab7}a.text-primary:hover,a.text-primary:focus{color:#286090}.text-success{color:#3c763d}a.text-success:hover,a.text-success:focus{color:#2b542c}.text-info{color:#31708f}a.text-info:hover,a.text-info:focus{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover,a.text-warning:focus{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover,a.text-danger:focus{color:#843534}.bg-primary{color:#fff;background-color:#337ab7}a.bg-primary:hover,a.bg-primary:focus{background-color:#286090}.bg-success{background-color:#dff0d8}a.bg-success:hover,a.bg-success:focus{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover,a.bg-info:focus{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover,a.bg-warning:focus{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover,a.bg-danger:focus{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none;margin-left:-5px}.list-inline>li{display:inline-block;padding-right:5px;padding-left:5px}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width: 768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eeeeee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.42857143;color:#777}blockquote footer:before,blockquote small:before,blockquote .small:before{content:"\2014\a0"}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;text-align:right;border-right:5px solid #eeeeee;border-left:0}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:""}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:"\a0\2014"}address{margin-bottom:20px;font-style:normal;line-height:1.42857143}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,Courier New,monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.25);box-shadow:inset 0 -1px #00000040}kbd kbd{padding:0;font-size:100%;font-weight:700;-webkit-box-shadow:none;box-shadow:none}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.42857143;color:#333;word-break:break-all;word-wrap:break-word;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width: 768px){.container{width:750px}}@media (min-width: 992px){.container{width:970px}}@media (min-width: 1200px){.container{width:1170px}}.container-fluid{padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{margin-right:-15px;margin-left:-15px}.row-no-gutters{margin-right:0;margin-left:0}.row-no-gutters [class*=col-]{padding-right:0;padding-left:0}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-right:15px;padding-left:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666667%}.col-xs-10{width:83.33333333%}.col-xs-9{width:75%}.col-xs-8{width:66.66666667%}.col-xs-7{width:58.33333333%}.col-xs-6{width:50%}.col-xs-5{width:41.66666667%}.col-xs-4{width:33.33333333%}.col-xs-3{width:25%}.col-xs-2{width:16.66666667%}.col-xs-1{width:8.33333333%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666667%}.col-xs-pull-10{right:83.33333333%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666667%}.col-xs-pull-7{right:58.33333333%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666667%}.col-xs-pull-4{right:33.33333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.66666667%}.col-xs-pull-1{right:8.33333333%}.col-xs-pull-0{right:auto}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666667%}.col-xs-push-10{left:83.33333333%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666667%}.col-xs-push-7{left:58.33333333%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666667%}.col-xs-push-4{left:33.33333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.66666667%}.col-xs-push-1{left:8.33333333%}.col-xs-push-0{left:auto}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666667%}.col-xs-offset-10{margin-left:83.33333333%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666667%}.col-xs-offset-7{margin-left:58.33333333%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666667%}.col-xs-offset-4{margin-left:33.33333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.66666667%}.col-xs-offset-1{margin-left:8.33333333%}.col-xs-offset-0{margin-left:0%}@media (min-width: 768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666667%}.col-sm-10{width:83.33333333%}.col-sm-9{width:75%}.col-sm-8{width:66.66666667%}.col-sm-7{width:58.33333333%}.col-sm-6{width:50%}.col-sm-5{width:41.66666667%}.col-sm-4{width:33.33333333%}.col-sm-3{width:25%}.col-sm-2{width:16.66666667%}.col-sm-1{width:8.33333333%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666667%}.col-sm-pull-10{right:83.33333333%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666667%}.col-sm-pull-7{right:58.33333333%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666667%}.col-sm-pull-4{right:33.33333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.66666667%}.col-sm-pull-1{right:8.33333333%}.col-sm-pull-0{right:auto}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666667%}.col-sm-push-10{left:83.33333333%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666667%}.col-sm-push-7{left:58.33333333%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666667%}.col-sm-push-4{left:33.33333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.66666667%}.col-sm-push-1{left:8.33333333%}.col-sm-push-0{left:auto}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666667%}.col-sm-offset-10{margin-left:83.33333333%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666667%}.col-sm-offset-7{margin-left:58.33333333%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666667%}.col-sm-offset-4{margin-left:33.33333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.66666667%}.col-sm-offset-1{margin-left:8.33333333%}.col-sm-offset-0{margin-left:0%}}@media (min-width: 992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666667%}.col-md-10{width:83.33333333%}.col-md-9{width:75%}.col-md-8{width:66.66666667%}.col-md-7{width:58.33333333%}.col-md-6{width:50%}.col-md-5{width:41.66666667%}.col-md-4{width:33.33333333%}.col-md-3{width:25%}.col-md-2{width:16.66666667%}.col-md-1{width:8.33333333%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666667%}.col-md-pull-10{right:83.33333333%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666667%}.col-md-pull-7{right:58.33333333%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666667%}.col-md-pull-4{right:33.33333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.66666667%}.col-md-pull-1{right:8.33333333%}.col-md-pull-0{right:auto}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666667%}.col-md-push-10{left:83.33333333%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666667%}.col-md-push-7{left:58.33333333%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666667%}.col-md-push-4{left:33.33333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.66666667%}.col-md-push-1{left:8.33333333%}.col-md-push-0{left:auto}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666667%}.col-md-offset-10{margin-left:83.33333333%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666667%}.col-md-offset-7{margin-left:58.33333333%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666667%}.col-md-offset-4{margin-left:33.33333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.66666667%}.col-md-offset-1{margin-left:8.33333333%}.col-md-offset-0{margin-left:0%}}@media (min-width: 1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666667%}.col-lg-10{width:83.33333333%}.col-lg-9{width:75%}.col-lg-8{width:66.66666667%}.col-lg-7{width:58.33333333%}.col-lg-6{width:50%}.col-lg-5{width:41.66666667%}.col-lg-4{width:33.33333333%}.col-lg-3{width:25%}.col-lg-2{width:16.66666667%}.col-lg-1{width:8.33333333%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666667%}.col-lg-pull-10{right:83.33333333%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666667%}.col-lg-pull-7{right:58.33333333%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666667%}.col-lg-pull-4{right:33.33333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.66666667%}.col-lg-pull-1{right:8.33333333%}.col-lg-pull-0{right:auto}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666667%}.col-lg-push-10{left:83.33333333%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666667%}.col-lg-push-7{left:58.33333333%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666667%}.col-lg-push-4{left:33.33333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.66666667%}.col-lg-push-1{left:8.33333333%}.col-lg-push-0{left:auto}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666667%}.col-lg-offset-10{margin-left:83.33333333%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666667%}.col-lg-offset-7{margin-left:58.33333333%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666667%}.col-lg-offset-4{margin-left:33.33333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.66666667%}.col-lg-offset-1{margin-left:8.33333333%}.col-lg-offset-0{margin-left:0%}}table{background-color:transparent}table col[class*=col-]{position:static;display:table-column;float:none}table td[class*=col-],table th[class*=col-]{position:static;display:table-cell;float:none}caption{padding-top:8px;padding-bottom:8px;color:#777;text-align:left}th{text-align:left}.table{width:100%;max-width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.42857143;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.table>thead:first-child>tr:first-child>td{border-top:0}.table>tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.table-striped>tbody>tr:nth-of-type(odd){background-color:#f9f9f9}.table-hover>tbody>tr:hover{background-color:#f5f5f5}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr:hover>.active,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr:hover>.success,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr:hover>.info,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr:hover>.warning,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr:hover>.danger,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}.table-responsive{min-height:.01%;overflow-x:auto}@media screen and (max-width: 767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-appearance:none;-moz-appearance:none;appearance:none}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \ ;line-height:normal}input[type=radio][disabled],input[type=checkbox][disabled],input[type=radio].disabled,input[type=checkbox].disabled,fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox]{cursor:not-allowed}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.42857143;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013;-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-o-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;-webkit-transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s,-webkit-box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px #00000013,0 0 8px #66afe999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control::-ms-expand{background-color:transparent;border:0}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{background-color:#eee;opacity:1}.form-control[disabled],fieldset[disabled] .form-control{cursor:not-allowed}textarea.form-control{height:auto}@media screen and (-webkit-min-device-pixel-ratio: 0){input[type=date].form-control,input[type=time].form-control,input[type=datetime-local].form-control,input[type=month].form-control{line-height:34px}input[type=date].input-sm,input[type=time].input-sm,input[type=datetime-local].input-sm,input[type=month].input-sm,.input-group-sm input[type=date],.input-group-sm input[type=time],.input-group-sm input[type=datetime-local],.input-group-sm input[type=month]{line-height:30px}input[type=date].input-lg,input[type=time].input-lg,input[type=datetime-local].input-lg,input[type=month].input-lg,.input-group-lg input[type=date],.input-group-lg input[type=time],.input-group-lg input[type=datetime-local],.input-group-lg input[type=month]{line-height:46px}}.form-group{margin-bottom:15px}.radio,.checkbox{position:relative;display:block;margin-top:10px;margin-bottom:10px}.radio.disabled label,.checkbox.disabled label,fieldset[disabled] .radio label,fieldset[disabled] .checkbox label{cursor:not-allowed}.radio label,.checkbox label{min-height:20px;padding-left:20px;margin-bottom:0;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{position:absolute;margin-top:4px \ ;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{position:relative;display:inline-block;padding-left:20px;margin-bottom:0;font-weight:400;vertical-align:middle;cursor:pointer}.radio-inline.disabled,.checkbox-inline.disabled,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}.form-control-static{min-height:34px;padding-top:7px;padding-bottom:7px;margin-bottom:0}.form-control-static.input-lg,.form-control-static.input-sm{padding-right:0;padding-left:0}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.form-group-sm .form-control{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.form-group-sm select.form-control{height:30px;line-height:30px}.form-group-sm textarea.form-control,.form-group-sm select[multiple].form-control{height:auto}.form-group-sm .form-control-static{height:30px;min-height:32px;padding:6px 10px;font-size:12px;line-height:1.5}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.form-group-lg .form-control{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.form-group-lg select.form-control{height:46px;line-height:46px}.form-group-lg textarea.form-control,.form-group-lg select[multiple].form-control{height:auto}.form-group-lg .form-control-static{height:46px;min-height:38px;padding:11px 16px;font-size:18px;line-height:1.3333333}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.form-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center;pointer-events:none}.input-lg+.form-control-feedback,.input-group-lg+.form-control-feedback,.form-group-lg .form-control+.form-control-feedback{width:46px;height:46px;line-height:46px}.input-sm+.form-control-feedback,.input-group-sm+.form-control-feedback,.form-group-sm .form-control+.form-control-feedback{width:30px;height:30px;line-height:30px}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline,.has-success.radio label,.has-success.checkbox label,.has-success.radio-inline label,.has-success.checkbox-inline label{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px #00000013,0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;background-color:#dff0d8;border-color:#3c763d}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline,.has-warning.radio label,.has-warning.checkbox label,.has-warning.radio-inline label,.has-warning.checkbox-inline label{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px #00000013,0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;background-color:#fcf8e3;border-color:#8a6d3b}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline,.has-error.radio label,.has-error.checkbox label,.has-error.radio-inline label,.has-error.checkbox-inline label{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px #00000013}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px #00000013,0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;background-color:#f2dede;border-color:#a94442}.has-error .form-control-feedback{color:#a94442}.has-feedback label~.form-control-feedback{top:25px}.has-feedback label.sr-only~.form-control-feedback{top:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width: 768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .form-control-static{display:inline-block}.form-inline .input-group{display:inline-table;vertical-align:middle}.form-inline .input-group .input-group-addon,.form-inline .input-group .input-group-btn,.form-inline .input-group .form-control{width:auto}.form-inline .input-group>.form-control{width:100%}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.form-inline .radio label,.form-inline .checkbox label{padding-left:0}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{position:relative;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{padding-top:7px;margin-top:0;margin-bottom:0}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-right:-15px;margin-left:-15px}@media (min-width: 768px){.form-horizontal .control-label{padding-top:7px;margin-bottom:0;text-align:right}}.form-horizontal .has-feedback .form-control-feedback{right:15px}@media (min-width: 768px){.form-horizontal .form-group-lg .control-label{padding-top:11px;font-size:18px}}@media (min-width: 768px){.form-horizontal .form-group-sm .control-label{padding-top:6px;font-size:12px}}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;cursor:pointer;background-image:none;border:1px solid transparent;padding:6px 12px;font-size:14px;line-height:1.42857143;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.btn:focus,.btn:active:focus,.btn.active:focus,.btn.focus,.btn:active.focus,.btn.active.focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus,.btn.focus{color:#333;text-decoration:none}.btn:active,.btn.active{background-image:none;outline:0;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px #00000020}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;filter:alpha(opacity=65);opacity:.65;-webkit-box-shadow:none;box-shadow:none}a.btn.disabled,fieldset[disabled] a.btn{pointer-events:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:focus,.btn-default.focus{color:#333;background-color:#e6e6e6;border-color:#8c8c8c}.btn-default:hover{color:#333;background-color:#e6e6e6;border-color:#adadad}.btn-default:active,.btn-default.active,.open>.dropdown-toggle.btn-default{color:#333;background-color:#e6e6e6;background-image:none;border-color:#adadad}.btn-default:active:hover,.btn-default.active:hover,.open>.dropdown-toggle.btn-default:hover,.btn-default:active:focus,.btn-default.active:focus,.open>.dropdown-toggle.btn-default:focus,.btn-default:active.focus,.btn-default.active.focus,.open>.dropdown-toggle.btn-default.focus{color:#333;background-color:#d4d4d4;border-color:#8c8c8c}.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled.focus,.btn-default[disabled].focus,fieldset[disabled] .btn-default.focus{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#337ab7;border-color:#2e6da4}.btn-primary:focus,.btn-primary.focus{color:#fff;background-color:#286090;border-color:#122b40}.btn-primary:hover{color:#fff;background-color:#286090;border-color:#204d74}.btn-primary:active,.btn-primary.active,.open>.dropdown-toggle.btn-primary{color:#fff;background-color:#286090;background-image:none;border-color:#204d74}.btn-primary:active:hover,.btn-primary.active:hover,.open>.dropdown-toggle.btn-primary:hover,.btn-primary:active:focus,.btn-primary.active:focus,.open>.dropdown-toggle.btn-primary:focus,.btn-primary:active.focus,.btn-primary.active.focus,.open>.dropdown-toggle.btn-primary.focus{color:#fff;background-color:#204d74;border-color:#122b40}.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled.focus,.btn-primary[disabled].focus,fieldset[disabled] .btn-primary.focus{background-color:#337ab7;border-color:#2e6da4}.btn-primary .badge{color:#337ab7;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:focus,.btn-success.focus{color:#fff;background-color:#449d44;border-color:#255625}.btn-success:hover{color:#fff;background-color:#449d44;border-color:#398439}.btn-success:active,.btn-success.active,.open>.dropdown-toggle.btn-success{color:#fff;background-color:#449d44;background-image:none;border-color:#398439}.btn-success:active:hover,.btn-success.active:hover,.open>.dropdown-toggle.btn-success:hover,.btn-success:active:focus,.btn-success.active:focus,.open>.dropdown-toggle.btn-success:focus,.btn-success:active.focus,.btn-success.active.focus,.open>.dropdown-toggle.btn-success.focus{color:#fff;background-color:#398439;border-color:#255625}.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled.focus,.btn-success[disabled].focus,fieldset[disabled] .btn-success.focus{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:focus,.btn-info.focus{color:#fff;background-color:#31b0d5;border-color:#1b6d85}.btn-info:hover{color:#fff;background-color:#31b0d5;border-color:#269abc}.btn-info:active,.btn-info.active,.open>.dropdown-toggle.btn-info{color:#fff;background-color:#31b0d5;background-image:none;border-color:#269abc}.btn-info:active:hover,.btn-info.active:hover,.open>.dropdown-toggle.btn-info:hover,.btn-info:active:focus,.btn-info.active:focus,.open>.dropdown-toggle.btn-info:focus,.btn-info:active.focus,.btn-info.active.focus,.open>.dropdown-toggle.btn-info.focus{color:#fff;background-color:#269abc;border-color:#1b6d85}.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled.focus,.btn-info[disabled].focus,fieldset[disabled] .btn-info.focus{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:focus,.btn-warning.focus{color:#fff;background-color:#ec971f;border-color:#985f0d}.btn-warning:hover{color:#fff;background-color:#ec971f;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open>.dropdown-toggle.btn-warning{color:#fff;background-color:#ec971f;background-image:none;border-color:#d58512}.btn-warning:active:hover,.btn-warning.active:hover,.open>.dropdown-toggle.btn-warning:hover,.btn-warning:active:focus,.btn-warning.active:focus,.open>.dropdown-toggle.btn-warning:focus,.btn-warning:active.focus,.btn-warning.active.focus,.open>.dropdown-toggle.btn-warning.focus{color:#fff;background-color:#d58512;border-color:#985f0d}.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled.focus,.btn-warning[disabled].focus,fieldset[disabled] .btn-warning.focus{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:focus,.btn-danger.focus{color:#fff;background-color:#c9302c;border-color:#761c19}.btn-danger:hover{color:#fff;background-color:#c9302c;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open>.dropdown-toggle.btn-danger{color:#fff;background-color:#c9302c;background-image:none;border-color:#ac2925}.btn-danger:active:hover,.btn-danger.active:hover,.open>.dropdown-toggle.btn-danger:hover,.btn-danger:active:focus,.btn-danger.active:focus,.open>.dropdown-toggle.btn-danger:focus,.btn-danger:active.focus,.btn-danger.active.focus,.open>.dropdown-toggle.btn-danger.focus{color:#fff;background-color:#ac2925;border-color:#761c19}.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled.focus,.btn-danger[disabled].focus,fieldset[disabled] .btn-danger.focus{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{font-weight:400;color:#337ab7;border-radius:0}.btn-link,.btn-link:active,.btn-link.active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#23527c;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#777;text-decoration:none}.btn-lg,.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}.btn-sm,.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs,.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}tr.collapse.in{display:table-row}tbody.collapse.in{display:table-row-group}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition-property:height,visibility;-o-transition-property:height,visibility;transition-property:height,visibility;-webkit-transition-duration:.35s;-o-transition-duration:.35s;transition-duration:.35s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px dashed;border-top:4px solid \ ;border-right:4px solid transparent;border-left:4px solid transparent}.dropup,.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px #0000002d}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{color:#262626;text-decoration:none;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#337ab7;outline:0}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#777}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:not-allowed;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{right:0;left:auto}.dropdown-menu-left{right:auto;left:0}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.42857143;color:#777;white-space:nowrap}.dropdown-backdrop{position:fixed;inset:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{content:"";border-top:0;border-bottom:4px dashed;border-bottom:4px solid \ }.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:2px}@media (min-width: 768px){.navbar-right .dropdown-menu{right:0;left:auto}.navbar-right .dropdown-menu-left{right:auto;left:0}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn,.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{padding-right:8px;padding-left:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-right:12px;padding-left:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px #00000020}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child:not(:first-child){border-radius:0 0 4px 4px}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-left-radius:0;border-top-right-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{display:table-cell;float:none;width:1%}.btn-group-justified>.btn-group .btn{width:100%}.btn-group-justified>.btn-group .dropdown-menu{left:auto}[data-toggle=buttons]>.btn input[type=radio],[data-toggle=buttons]>.btn-group>.btn input[type=radio],[data-toggle=buttons]>.btn input[type=checkbox],[data-toggle=buttons]>.btn-group>.btn input[type=checkbox]{position:absolute;clip:rect(0,0,0,0);pointer-events:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-right:0;padding-left:0}.input-group .form-control{position:relative;z-index:2;float:left;width:100%;margin-bottom:0}.input-group .form-control:focus{z-index:3}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.3333333;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-top-right-radius:0;border-bottom-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-top-left-radius:0;border-bottom-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{z-index:2;margin-left:-1px}.nav{padding-left:0;margin-bottom:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#777}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#777;text-decoration:none;cursor:not-allowed;background-color:transparent}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#337ab7}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.42857143;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eeeeee #eeeeee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width: 768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width: 768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#337ab7}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{margin-bottom:5px;text-align:center}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width: 768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width: 768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-left-radius:0;border-top-right-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width: 768px){.navbar{border-radius:4px}}@media (min-width: 768px){.navbar-header{float:left}}.navbar-collapse{padding-right:15px;padding-left:15px;overflow-x:visible;border-top:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px #ffffff1a;-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width: 768px){.navbar-collapse{width:auto;border-top:0;-webkit-box-shadow:none;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-right:0;padding-left:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:340px}@media (max-device-width: 480px) and (orientation: landscape){.navbar-fixed-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{max-height:200px}}@media (min-width: 768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width: 768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width: 768px){.navbar-static-top{border-radius:0}}.navbar-brand{float:left;height:50px;padding:15px;font-size:18px;line-height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}.navbar-brand>img{display:block}@media (min-width: 768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;padding:9px 10px;margin-right:15px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width: 768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width: 767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width: 768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}}.navbar-form{padding:10px 15px;margin:8px -15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px #ffffff1a,0 1px #ffffff1a}@media (min-width: 768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .form-control-static{display:inline-block}.navbar-form .input-group{display:inline-table;vertical-align:middle}.navbar-form .input-group .input-group-addon,.navbar-form .input-group .input-group-btn,.navbar-form .input-group .form-control{width:auto}.navbar-form .input-group>.form-control{width:100%}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;vertical-align:middle}.navbar-form .radio label,.navbar-form .checkbox label{padding-left:0}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{position:relative;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width: 767px){.navbar-form .form-group{margin-bottom:5px}.navbar-form .form-group:last-child{margin-bottom:0}}@media (min-width: 768px){.navbar-form{width:auto;padding-top:0;padding-bottom:0;margin-right:0;margin-left:0;border:0;-webkit-box-shadow:none;box-shadow:none}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-left-radius:0;border-top-right-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{margin-bottom:0;border-radius:4px 4px 0 0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width: 768px){.navbar-text{float:left;margin-right:15px;margin-left:15px}}@media (min-width: 768px){.navbar-left{float:left!important}.navbar-right{float:right!important;margin-right:-15px}.navbar-right~.navbar-right{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{color:#555;background-color:#e7e7e7}@media (max-width: 767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-default .btn-link{color:#777}.navbar-default .btn-link:hover,.navbar-default .btn-link:focus{color:#333}.navbar-default .btn-link[disabled]:hover,fieldset[disabled] .navbar-default .btn-link:hover,.navbar-default .btn-link[disabled]:focus,fieldset[disabled] .navbar-default .btn-link:focus{color:#ccc}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#9d9d9d}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{color:#fff;background-color:#080808}@media (max-width: 767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#9d9d9d}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-link{color:#9d9d9d}.navbar-inverse .navbar-link:hover{color:#fff}.navbar-inverse .btn-link{color:#9d9d9d}.navbar-inverse .btn-link:hover,.navbar-inverse .btn-link:focus{color:#fff}.navbar-inverse .btn-link[disabled]:hover,fieldset[disabled] .navbar-inverse .btn-link:hover,.navbar-inverse .btn-link[disabled]:focus,fieldset[disabled] .navbar-inverse .btn-link:focus{color:#444}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{padding:0 5px;color:#ccc;content:"/\a0"}.breadcrumb>.active{color:#777}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;margin-left:-1px;line-height:1.42857143;color:#337ab7;text-decoration:none;background-color:#fff;border:1px solid #ddd}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{z-index:2;color:#23527c;background-color:#eee;border-color:#ddd}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-top-left-radius:4px;border-bottom-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-top-right-radius:4px;border-bottom-right-radius:4px}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:3;color:#fff;cursor:default;background-color:#337ab7;border-color:#337ab7}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#777;cursor:not-allowed;background-color:#fff;border-color:#ddd}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px;line-height:1.3333333}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-top-left-radius:6px;border-bottom-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-top-right-radius:6px;border-bottom-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px;line-height:1.5}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-top-left-radius:3px;border-bottom-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-top-right-radius:3px;border-bottom-right-radius:3px}.pager{padding-left:0;margin:20px 0;text-align:center;list-style:none}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#777;cursor:not-allowed;background-color:#fff}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}a.label:hover,a.label:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#777}.label-default[href]:hover,.label-default[href]:focus{background-color:#5e5e5e}.label-primary{background-color:#337ab7}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#286090}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:middle;background-color:#777;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge,.btn-group-xs>.btn .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#337ab7;background-color:#fff}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding-top:30px;padding-bottom:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.jumbotron>hr{border-top-color:#d5d5d5}.container .jumbotron,.container-fluid .jumbotron{padding-right:15px;padding-left:15px;border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width: 768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron,.container-fluid .jumbotron{padding-right:60px;padding-left:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:border .2s ease-in-out;-o-transition:border .2s ease-in-out;transition:border .2s ease-in-out}.thumbnail>img,.thumbnail a>img{margin-right:auto;margin-left:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#337ab7}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable,.alert-dismissible{padding-right:35px}.alert-dismissable .close,.alert-dismissible .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{0%{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px #0000001a}.progress-bar{float:left;width:0%;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#337ab7;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px #00000026;-webkit-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar,.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;background-size:40px 40px}.progress.active .progress-bar,.progress-bar.active{-webkit-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media{margin-top:15px}.media:first-child{margin-top:0}.media,.media-body{overflow:hidden;zoom:1}.media-body{width:10000px}.media-object{display:block}.media-object.img-thumbnail{max-width:none}.media-right,.media>.pull-right{padding-left:10px}.media-left,.media>.pull-left{padding-right:10px}.media-left,.media-right,.media-body{display:table-cell;vertical-align:top}.media-middle{vertical-align:middle}.media-bottom{vertical-align:bottom}.media-heading{margin-top:0;margin-bottom:5px}.media-list{padding-left:0;list-style:none}.list-group{padding-left:0;margin-bottom:20px}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item.disabled,.list-group-item.disabled:hover,.list-group-item.disabled:focus{color:#777;cursor:not-allowed;background-color:#eee}.list-group-item.disabled .list-group-item-heading,.list-group-item.disabled:hover .list-group-item-heading,.list-group-item.disabled:focus .list-group-item-heading{color:inherit}.list-group-item.disabled .list-group-item-text,.list-group-item.disabled:hover .list-group-item-text,.list-group-item.disabled:focus .list-group-item-text{color:#777}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{z-index:2;color:#fff;background-color:#337ab7;border-color:#337ab7}.list-group-item.active .list-group-item-heading,.list-group-item.active:hover .list-group-item-heading,.list-group-item.active:focus .list-group-item-heading,.list-group-item.active .list-group-item-heading>small,.list-group-item.active:hover .list-group-item-heading>small,.list-group-item.active:focus .list-group-item-heading>small,.list-group-item.active .list-group-item-heading>.small,.list-group-item.active:hover .list-group-item-heading>.small,.list-group-item.active:focus .list-group-item-heading>.small{color:inherit}.list-group-item.active .list-group-item-text,.list-group-item.active:hover .list-group-item-text,.list-group-item.active:focus .list-group-item-text{color:#c7ddef}a.list-group-item,button.list-group-item{color:#555}a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{color:#555;text-decoration:none;background-color:#f5f5f5}button.list-group-item{width:100%;text-align:left}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success,button.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading,button.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,button.list-group-item-success:hover,a.list-group-item-success:focus,button.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,button.list-group-item-success.active,a.list-group-item-success.active:hover,button.list-group-item-success.active:hover,a.list-group-item-success.active:focus,button.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info,button.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,button.list-group-item-info:hover,a.list-group-item-info:focus,button.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,button.list-group-item-info.active,a.list-group-item-info.active:hover,button.list-group-item-info.active:hover,a.list-group-item-info.active:focus,button.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading,button.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,button.list-group-item-warning:hover,a.list-group-item-warning:focus,button.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,button.list-group-item-warning.active,a.list-group-item-warning.active:hover,button.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus,button.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger,button.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading,button.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,button.list-group-item-danger:hover,a.list-group-item-danger:focus,button.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,button.list-group-item-danger.active,a.list-group-item-danger.active:hover,button.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus,button.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px #0000000d}.panel-body{padding:15px}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-left-radius:3px;border-top-right-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a,.panel-title>small,.panel-title>.small,.panel-title>small>a,.panel-title>.small>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.list-group,.panel>.panel-collapse>.list-group{margin-bottom:0}.panel>.list-group .list-group-item,.panel>.panel-collapse>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group:first-child .list-group-item:first-child,.panel>.panel-collapse>.list-group:first-child .list-group-item:first-child{border-top:0;border-top-left-radius:3px;border-top-right-radius:3px}.panel>.list-group:last-child .list-group-item:last-child,.panel>.panel-collapse>.list-group:last-child .list-group-item:last-child{border-bottom:0;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.panel-heading+.panel-collapse>.list-group .list-group-item:first-child{border-top-left-radius:0;border-top-right-radius:0}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.list-group+.panel-footer{border-top-width:0}.panel>.table,.panel>.table-responsive>.table,.panel>.panel-collapse>.table{margin-bottom:0}.panel>.table caption,.panel>.table-responsive>.table caption,.panel>.panel-collapse>.table caption{padding-right:15px;padding-left:15px}.panel>.table:first-child,.panel>.table-responsive:first-child>.table:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child{border-top-left-radius:3px;border-top-right-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child,.panel>.table-responsive:last-child>.table:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive,.panel>.table+.panel-body,.panel>.table-responsive+.panel-body{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th{border-bottom:0}.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th{border-bottom:0}.panel>.table-responsive{margin-bottom:0;border:0}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse>.panel-body,.panel-group .panel-heading+.panel-collapse>.list-group{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ddd}.panel-default>.panel-heading .badge{color:#f5f5f5;background-color:#333}.panel-default>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#337ab7}.panel-primary>.panel-heading{color:#fff;background-color:#337ab7;border-color:#337ab7}.panel-primary>.panel-heading+.panel-collapse>.panel-body{border-top-color:#337ab7}.panel-primary>.panel-heading .badge{color:#337ab7;background-color:#fff}.panel-primary>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#337ab7}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse>.panel-body{border-top-color:#d6e9c6}.panel-success>.panel-heading .badge{color:#dff0d8;background-color:#3c763d}.panel-success>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse>.panel-body{border-top-color:#bce8f1}.panel-info>.panel-heading .badge{color:#d9edf7;background-color:#31708f}.panel-info>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse>.panel-body{border-top-color:#faebcc}.panel-warning>.panel-heading .badge{color:#fcf8e3;background-color:#8a6d3b}.panel-warning>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse>.panel-body{border-top-color:#ebccd1}.panel-danger>.panel-heading .badge{color:#f2dede;background-color:#a94442}.panel-danger>.panel-footer+.panel-collapse>.panel-body{border-bottom-color:#ebccd1}.embed-responsive{position:relative;display:block;height:0;padding:0;overflow:hidden}.embed-responsive .embed-responsive-item,.embed-responsive iframe,.embed-responsive embed,.embed-responsive object,.embed-responsive video{position:absolute;top:0;bottom:0;left:0;width:100%;height:100%;border:0}.embed-responsive-16by9{padding-bottom:56.25%}.embed-responsive-4by3{padding-bottom:75%}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px #0000000d}.well blockquote{border-color:#ddd;border-color:#00000026}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;-moz-appearance:none;appearance:none}.modal-open{overflow:hidden}.modal{position:fixed;inset:0;z-index:1050;display:none;overflow:hidden;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);-o-transform:translate(0,-25%);transform:translateY(-25%);-webkit-transition:-webkit-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:-webkit-transform .3s ease-out;transition:transform .3s ease-out;transition:transform .3s ease-out,-webkit-transform .3s ease-out,-o-transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);-o-transform:translate(0,0);transform:translate(0)}.modal-open .modal{overflow-x:hidden;overflow-y:auto}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;background-clip:padding-box;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px #00000080;outline:0}.modal-backdrop{position:fixed;inset:0;z-index:1040;background-color:#000}.modal-backdrop.fade{filter:alpha(opacity=0);opacity:0}.modal-backdrop.in{filter:alpha(opacity=50);opacity:.5}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.42857143}.modal-body{position:relative;padding:15px}.modal-footer{padding:15px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.modal-scrollbar-measure{position:absolute;top:-9999px;width:50px;height:50px;overflow:scroll}@media (min-width: 768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px #00000080}.modal-sm{width:300px}}@media (min-width: 992px){.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1070;display:block;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:12px;filter:alpha(opacity=0);opacity:0}.tooltip.in{filter:alpha(opacity=90);opacity:.9}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{right:5px;bottom:0;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;left:5px;margin-bottom:-5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;right:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;left:5px;margin-top:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;background-color:#000;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.popover{position:absolute;top:0;left:0;z-index:1060;display:none;max-width:276px;padding:1px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-style:normal;font-weight:400;line-height:1.42857143;line-break:auto;text-align:left;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;font-size:14px;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px #0003}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover>.arrow{border-width:11px}.popover>.arrow,.popover>.arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover>.arrow:after{content:"";border-width:10px}.popover.top>.arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:#00000040;border-bottom-width:0}.popover.top>.arrow:after{bottom:1px;margin-left:-10px;content:" ";border-top-color:#fff;border-bottom-width:0}.popover.right>.arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:#00000040;border-left-width:0}.popover.right>.arrow:after{bottom:-10px;left:1px;content:" ";border-right-color:#fff;border-left-width:0}.popover.bottom>.arrow{top:-11px;left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:#00000040}.popover.bottom>.arrow:after{top:1px;margin-left:-10px;content:" ";border-top-width:0;border-bottom-color:#fff}.popover.left>.arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:#00000040}.popover.left>.arrow:after{right:1px;bottom:-10px;content:" ";border-right-width:0;border-left-color:#fff}.popover-title{padding:8px 14px;margin:0;font-size:14px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.popover-content{padding:9px 14px}.carousel{position:relative}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{line-height:1}@media all and (transform-3d),(-webkit-transform-3d){.carousel-inner>.item{-webkit-transition:-webkit-transform .6s ease-in-out;-o-transition:-o-transform .6s ease-in-out;transition:-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out;transition:transform .6s ease-in-out,-webkit-transform .6s ease-in-out,-o-transform .6s ease-in-out;-webkit-backface-visibility:hidden;backface-visibility:hidden;-webkit-perspective:1000px;perspective:1000px}.carousel-inner>.item.next,.carousel-inner>.item.active.right{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);left:0}.carousel-inner>.item.prev,.carousel-inner>.item.active.left{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);left:0}.carousel-inner>.item.next.left,.carousel-inner>.item.prev.right,.carousel-inner>.item.active{-webkit-transform:translate3d(0,0,0);transform:translateZ(0);left:0}}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:0;bottom:0;left:0;width:15%;font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6);background-color:#0000;filter:alpha(opacity=50);opacity:.5}.carousel-control.left{background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,.0001)));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0%,rgba(0,0,0,.0001) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#80000000",endColorstr="#00000000",GradientType=1);background-repeat:repeat-x}.carousel-control.right{right:0;left:auto;background-image:-webkit-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:-o-linear-gradient(left,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.0001)),to(rgba(0,0,0,.5)));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0%,rgba(0,0,0,.5) 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr="#00000000",endColorstr="#80000000",GradientType=1);background-repeat:repeat-x}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;outline:0;filter:alpha(opacity=90);opacity:.9}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block;margin-top:-10px}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%;margin-left:-10px}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%;margin-right:-10px}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;font-family:serif;line-height:1}.carousel-control .icon-prev:before{content:"\2039"}.carousel-control .icon-next:before{content:"\203a"}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;padding-left:0;margin-left:-30%;text-align:center;list-style:none}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;cursor:pointer;background-color:#000 \ ;background-color:#0000;border:1px solid #fff;border-radius:10px}.carousel-indicators .active{width:12px;height:12px;margin:0;background-color:#fff}.carousel-caption{position:absolute;right:15%;bottom:20px;left:15%;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width: 768px){.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-10px;font-size:30px}.carousel-control .glyphicon-chevron-left,.carousel-control .icon-prev{margin-left:-10px}.carousel-control .glyphicon-chevron-right,.carousel-control .icon-next{margin-right:-10px}.carousel-caption{right:20%;left:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.dl-horizontal dd:before,.dl-horizontal dd:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-header:before,.modal-header:after,.modal-footer:before,.modal-footer:after{display:table;content:" "}.clearfix:after,.dl-horizontal dd:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-header:after,.modal-footer:after{clear:both}.center-block{display:block;margin-right:auto;margin-left:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,.visible-sm,.visible-md,.visible-lg,.visible-xs-block,.visible-xs-inline,.visible-xs-inline-block,.visible-sm-block,.visible-sm-inline,.visible-sm-inline-block,.visible-md-block,.visible-md-inline,.visible-md-inline-block,.visible-lg-block,.visible-lg-inline,.visible-lg-inline-block{display:none!important}@media (max-width: 767px){.visible-xs{display:block!important}table.visible-xs{display:table!important}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}@media (max-width: 767px){.visible-xs-block{display:block!important}}@media (max-width: 767px){.visible-xs-inline{display:inline!important}}@media (max-width: 767px){.visible-xs-inline-block{display:inline-block!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm{display:block!important}table.visible-sm{display:table!important}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-block{display:block!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-inline{display:inline!important}}@media (min-width: 768px) and (max-width: 991px){.visible-sm-inline-block{display:inline-block!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md{display:block!important}table.visible-md{display:table!important}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-block{display:block!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-inline{display:inline!important}}@media (min-width: 992px) and (max-width: 1199px){.visible-md-inline-block{display:inline-block!important}}@media (min-width: 1200px){.visible-lg{display:block!important}table.visible-lg{display:table!important}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (min-width: 1200px){.visible-lg-block{display:block!important}}@media (min-width: 1200px){.visible-lg-inline{display:inline!important}}@media (min-width: 1200px){.visible-lg-inline-block{display:inline-block!important}}@media (max-width: 767px){.hidden-xs{display:none!important}}@media (min-width: 768px) and (max-width: 991px){.hidden-sm{display:none!important}}@media (min-width: 992px) and (max-width: 1199px){.hidden-md{display:none!important}}@media (min-width: 1200px){.hidden-lg{display:none!important}}.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table!important}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}.visible-print-block{display:none!important}@media print{.visible-print-block{display:block!important}}.visible-print-inline{display:none!important}@media print{.visible-print-inline{display:inline!important}}.visible-print-inline-block{display:none!important}@media print{.visible-print-inline-block{display:inline-block!important}}@media print{.hidden-print{display:none!important}}pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-variable{color:#005cc5}.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-code,.hljs-comment,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-pseudo,.hljs-selector-tag{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0} /*! Bundled license information: @default/bootstrap/dist/css/bootstrap.css: diff --git a/docs/styles/docfx.vendor.min.css.map b/docs/styles/docfx.vendor.min.css.map index 31cf61ec..ddb7afef 100644 --- a/docs/styles/docfx.vendor.min.css.map +++ b/docs/styles/docfx.vendor.min.css.map @@ -2,6 +2,6 @@ "version": 3, "sources": ["../../node_modules/@default/bootstrap/dist/css/bootstrap.css", "../../node_modules/@default/bootstrap/dist/css/less/normalize.less", "../../node_modules/@default/bootstrap/dist/css/less/print.less", "../../node_modules/@default/bootstrap/dist/css/less/glyphicons.less", "../../node_modules/@default/bootstrap/dist/css/less/scaffolding.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/vendor-prefixes.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/tab-focus.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/image.less", "../../node_modules/@default/bootstrap/dist/css/less/type.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/text-emphasis.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/background-variant.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/text-overflow.less", "../../node_modules/@default/bootstrap/dist/css/less/code.less", "../../node_modules/@default/bootstrap/dist/css/less/grid.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/grid.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/grid-framework.less", "../../node_modules/@default/bootstrap/dist/css/less/tables.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/table-row.less", "../../node_modules/@default/bootstrap/dist/css/less/forms.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/forms.less", "../../node_modules/@default/bootstrap/dist/css/less/buttons.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/buttons.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/opacity.less", "../../node_modules/@default/bootstrap/dist/css/less/component-animations.less", "../../node_modules/@default/bootstrap/dist/css/less/dropdowns.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/nav-divider.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/reset-filter.less", "../../node_modules/@default/bootstrap/dist/css/less/button-groups.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/border-radius.less", "../../node_modules/@default/bootstrap/dist/css/less/input-groups.less", "../../node_modules/@default/bootstrap/dist/css/less/navs.less", "../../node_modules/@default/bootstrap/dist/css/less/navbar.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/nav-vertical-align.less", "../../node_modules/@default/bootstrap/dist/css/less/utilities.less", "../../node_modules/@default/bootstrap/dist/css/less/breadcrumbs.less", "../../node_modules/@default/bootstrap/dist/css/less/pagination.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/pagination.less", "../../node_modules/@default/bootstrap/dist/css/less/pager.less", "../../node_modules/@default/bootstrap/dist/css/less/labels.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/labels.less", "../../node_modules/@default/bootstrap/dist/css/less/badges.less", "../../node_modules/@default/bootstrap/dist/css/less/jumbotron.less", "../../node_modules/@default/bootstrap/dist/css/less/thumbnails.less", "../../node_modules/@default/bootstrap/dist/css/less/alerts.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/alerts.less", "../../node_modules/@default/bootstrap/dist/css/less/progress-bars.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/gradients.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/progress-bar.less", "../../node_modules/@default/bootstrap/dist/css/less/media.less", "../../node_modules/@default/bootstrap/dist/css/less/list-group.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/list-group.less", "../../node_modules/@default/bootstrap/dist/css/less/panels.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/panels.less", "../../node_modules/@default/bootstrap/dist/css/less/responsive-embed.less", "../../node_modules/@default/bootstrap/dist/css/less/wells.less", "../../node_modules/@default/bootstrap/dist/css/less/close.less", "../../node_modules/@default/bootstrap/dist/css/less/modals.less", "../../node_modules/@default/bootstrap/dist/css/less/tooltip.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/reset-text.less", "../../node_modules/@default/bootstrap/dist/css/less/popovers.less", "../../node_modules/@default/bootstrap/dist/css/less/carousel.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/clearfix.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/center-block.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/hide-text.less", "../../node_modules/@default/bootstrap/dist/css/less/responsive-utilities.less", "../../node_modules/@default/bootstrap/dist/css/less/mixins/responsive-visibility.less", "../../node_modules/@default/highlight.js/styles/github.css"], "sourcesContent": ["/*!\n * Bootstrap v3.4.1 (https://getbootstrap.com/)\n * Copyright 2011-2019 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: none;\n text-decoration: underline;\n text-decoration: underline dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important;\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"../fonts/glyphicons-halflings-regular.eot\");\n src: url(\"../fonts/glyphicons-halflings-regular.eot?#iefix\") format(\"embedded-opentype\"), url(\"../fonts/glyphicons-halflings-regular.woff2\") format(\"woff2\"), url(\"../fonts/glyphicons-halflings-regular.woff\") format(\"woff\"), url(\"../fonts/glyphicons-halflings-regular.ttf\") format(\"truetype\"), url(\"../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular\") format(\"svg\");\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: 400;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: \"\\2014 \\00A0\";\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: \"\";\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: \"\\00A0 \\2014\";\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n color: #333333;\n word-break: break-all;\n word-wrap: break-word;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n.row {\n margin-right: -15px;\n margin-left: -15px;\n}\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n.row-no-gutters [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11,\n.col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1,\n .col-sm-2,\n .col-sm-3,\n .col-sm-4,\n .col-sm-5,\n .col-sm-6,\n .col-sm-7,\n .col-sm-8,\n .col-sm-9,\n .col-sm-10,\n .col-sm-11,\n .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1,\n .col-md-2,\n .col-md-3,\n .col-md-4,\n .col-md-5,\n .col-md-6,\n .col-md-7,\n .col-md-8,\n .col-md-9,\n .col-md-10,\n .col-md-11,\n .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1,\n .col-lg-2,\n .col-lg-3,\n .col-lg-4,\n .col-lg-5,\n .col-lg-6,\n .col-lg-7,\n .col-lg-8,\n .col-lg-9,\n .col-lg-10,\n .col-lg-11,\n .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ntable col[class*=\"col-\"] {\n position: static;\n display: table-column;\n float: none;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n display: table-cell;\n float: none;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n min-height: 0.01%;\n overflow-x: auto;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: 700;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n -webkit-appearance: none;\n appearance: none;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-top: 4px \\9;\n margin-left: -20px;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: 400;\n vertical-align: middle;\n cursor: pointer;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\n.form-control-static {\n min-height: 34px;\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-right: 0;\n padding-left: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #3c763d;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #8a6d3b;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n background-color: #f2dede;\n border-color: #a94442;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n padding-top: 7px;\n margin-top: 0;\n margin-bottom: 0;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n padding-top: 7px;\n margin-bottom: 0;\n text-align: right;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n outline: 0;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n filter: alpha(opacity=65);\n opacity: 0.65;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n background-image: none;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n background-image: none;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n background-image: none;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n background-image: none;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n background-image: none;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n background-image: none;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n font-weight: 400;\n color: #337ab7;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n font-size: 14px;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: 400;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n color: #262626;\n text-decoration: none;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n background-color: #337ab7;\n outline: 0;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu-left {\n right: auto;\n left: 0;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n content: \"\";\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n right: 0;\n left: auto;\n }\n .navbar-right .dropdown-menu-left {\n right: auto;\n left: 0;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-right: 8px;\n padding-left: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-right: 12px;\n padding-left: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n display: table-cell;\n float: none;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-right: 0;\n padding-left: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: 400;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n cursor: not-allowed;\n background-color: transparent;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n cursor: default;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n margin-bottom: 5px;\n text-align: center;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n padding-right: 15px;\n padding-left: 15px;\n overflow-x: visible;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-right: 0;\n padding-left: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-brand {\n float: left;\n height: 50px;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n padding: 9px 10px;\n margin-right: 15px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n padding: 10px 15px;\n margin-right: -15px;\n margin-left: -15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n padding-top: 0;\n padding-bottom: 0;\n margin-right: 0;\n margin-left: 0;\n border: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-right: 15px;\n margin-left: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n color: #fff;\n background-color: #080808;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n padding: 0 5px;\n color: #ccc;\n content: \"/\\00a0\";\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n margin-left: -1px;\n line-height: 1.42857143;\n color: #337ab7;\n text-decoration: none;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-top-left-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n cursor: default;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n border-color: #ddd;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-top-left-radius: 6px;\n border-bottom-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-top-right-radius: 6px;\n border-bottom-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-top-left-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-top-right-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n text-align: center;\n list-style: none;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n cursor: not-allowed;\n background-color: #fff;\n}\n.label {\n display: inline;\n padding: 0.2em 0.6em 0.3em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n padding-right: 15px;\n padding-left: 15px;\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-right: 60px;\n padding-left: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-right: auto;\n margin-left: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n height: 20px;\n margin-bottom: 20px;\n overflow: hidden;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n padding-left: 0;\n margin-bottom: 20px;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n color: #777777;\n cursor: not-allowed;\n background-color: #eeeeee;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n color: #555;\n text-decoration: none;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-right: 15px;\n padding-left: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n margin-bottom: 0;\n border: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n filter: alpha(opacity=20);\n opacity: 0.2;\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.modal-backdrop.in {\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-bottom: 0;\n margin-left: 5px;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 12px;\n filter: alpha(opacity=0);\n opacity: 0;\n}\n.tooltip.in {\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.tooltip.top {\n padding: 5px 0;\n margin-top: -3px;\n}\n.tooltip.right {\n padding: 0 5px;\n margin-left: 3px;\n}\n.tooltip.bottom {\n padding: 5px 0;\n margin-top: 3px;\n}\n.tooltip.left {\n padding: 0 5px;\n margin-left: -3px;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n right: 5px;\n bottom: 0;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: 400;\n line-height: 1.42857143;\n line-break: auto;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n white-space: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow:after {\n content: \"\";\n border-width: 10px;\n}\n.popover.top > .arrow {\n bottom: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n border-bottom-width: 0;\n}\n.popover.top > .arrow:after {\n bottom: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-color: #fff;\n border-bottom-width: 0;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n border-left-width: 0;\n}\n.popover.right > .arrow:after {\n bottom: -10px;\n left: 1px;\n content: \" \";\n border-right-color: #fff;\n border-left-width: 0;\n}\n.popover.bottom > .arrow {\n top: -11px;\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n.popover.bottom > .arrow:after {\n top: 1px;\n margin-left: -10px;\n content: \" \";\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n right: 1px;\n bottom: -10px;\n content: \" \";\n border-right-width: 0;\n border-left-color: #fff;\n}\n.popover-title {\n padding: 8px 14px;\n margin: 0;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n.carousel-inner > .item {\n position: relative;\n display: none;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 15%;\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n filter: alpha(opacity=50);\n opacity: 0.5;\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control.right {\n right: 0;\n left: auto;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n background-repeat: repeat-x;\n}\n.carousel-control:hover,\n.carousel-control:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n filter: alpha(opacity=90);\n opacity: 0.9;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n margin-top: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n font-family: serif;\n line-height: 1;\n}\n.carousel-control .icon-prev:before {\n content: \"\\2039\";\n}\n.carousel-control .icon-next:before {\n content: \"\\203a\";\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n padding-left: 0;\n margin-left: -30%;\n text-align: center;\n list-style: none;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n border: 1px solid #fff;\n border-radius: 10px;\n}\n.carousel-indicators .active {\n width: 12px;\n height: 12px;\n margin: 0;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n right: 20%;\n left: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n display: table;\n content: \" \";\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-right: auto;\n margin-left: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */", "// stylelint-disable\n\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// 1. Remove the bottom border in Chrome 57- and Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n//\n\nabbr[title] {\n border-bottom: none; // 1\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n", "// stylelint-disable declaration-no-important, selector-no-qualifying-type\n\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n color: #000 !important; // Black prints faster: h5bp.com/s\n text-shadow: none !important;\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n}\n", "// stylelint-disable value-list-comma-newline-after, value-list-comma-space-after, indentation, declaration-colon-newline-after, font-family-no-missing-generic-family-keyword\n\n//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: \"Glyphicons Halflings\";\n src: url(\"@{icon-font-path}@{icon-font-name}.eot\");\n src: url(\"@{icon-font-path}@{icon-font-name}.eot?#iefix\") format(\"embedded-opentype\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff2\") format(\"woff2\"),\n url(\"@{icon-font-path}@{icon-font-name}.woff\") format(\"woff\"),\n url(\"@{icon-font-path}@{icon-font-name}.ttf\") format(\"truetype\"),\n url(\"@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}\") format(\"svg\");\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: \"Glyphicons Halflings\";\n font-style: normal;\n font-weight: 400;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n", "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// https://getbootstrap.com/docs/3.4/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: https://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n", "// stylelint-disable indentation, property-no-vendor-prefix, selector-no-vendor-prefix\n\n// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n word-wrap: break-word;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n", "// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n", "// stylelint-disable media-feature-name-no-vendor-prefix, media-feature-parentheses-space-inside, media-feature-name-no-unknown, indentation, at-rule-name-space-after\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n", "// stylelint-disable selector-list-comma-newline-after, selector-no-qualifying-type\n\n//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: 400;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n padding: .2em;\n background-color: @state-warning-bg;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-right: 5px;\n padding-left: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: 700;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n}\n\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: \"\\2014 \\00A0\"; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n text-align: right;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: \"\"; }\n &:after {\n content: \"\\00A0 \\2014\"; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n", "// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n", "// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n", "// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n", "//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n color: @pre-color;\n word-break: break-all;\n word-wrap: break-word;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n", "//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n.row-no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n", "// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n padding-right: ceil((@gutter / 2));\n padding-left: floor((@gutter / 2));\n margin-right: auto;\n margin-left: auto;\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-right: floor((@gutter / -2));\n margin-left: ceil((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-right: (@gutter / 2);\n padding-left: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n", "// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-right: floor((@grid-gutter-width / 2));\n padding-left: ceil((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n", "// stylelint-disable selector-max-type, selector-max-compound-selectors, selector-no-qualifying-type\n\n//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n\n // Table cell sizing\n //\n // Reset default table behavior\n\n col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-column;\n float: none;\n }\n\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n display: table-cell;\n float: none;\n }\n }\n}\n\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\n\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n min-height: .01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n overflow-x: auto;\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * .75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n", "// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n", "// stylelint-disable selector-no-qualifying-type, property-no-vendor-prefix, media-feature-name-no-vendor-prefix\n\n//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: 700;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\ninput[type=\"search\"] {\n // Override content-box in Normalize (* isn't specific enough)\n .box-sizing(border-box);\n\n // Search inputs in iOS\n //\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n -webkit-appearance: none;\n appearance: none;\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n\n // Apply same disabled cursor tweak as for inputs\n // Some special care is needed because
    /// Request information (EndPoint, internal id, additional data) - void OnConnectionRequest(ConnectionRequest request); + void OnConnectionRequest(LiteConnectionRequest request); /// /// Called when peer address changed (when AllowPeerAddressChange is enabled) @@ -299,7 +299,7 @@ public class EventBasedLiteNetListener : ILiteNetEventListener 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(ConnectionRequest request); + public delegate void OnConnectionRequest(LiteConnectionRequest request); public delegate void OnDeliveryEvent(LiteNetPeer peer, object userData); public delegate void OnPeerAddressChangedEvent(LiteNetPeer peer, IPEndPoint previousAddress); @@ -341,7 +341,7 @@ void ILiteNetEventListener.OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint void ILiteNetEventListener.OnNetworkLatencyUpdate(LiteNetPeer peer, int latency) => NetworkLatencyUpdateEvent?.Invoke(peer, latency); - void ILiteNetEventListener.OnConnectionRequest(ConnectionRequest request) => + void ILiteNetEventListener.OnConnectionRequest(LiteConnectionRequest request) => ConnectionRequestEvent?.Invoke(request); void ILiteNetEventListener.OnMessageDelivered(LiteNetPeer peer, object userData) => diff --git a/LiteNetLib/InternalPackets.cs b/LiteNetLib/InternalPackets.cs index afce5ddf..6cd9a8db 100644 --- a/LiteNetLib/InternalPackets.cs +++ b/LiteNetLib/InternalPackets.cs @@ -4,7 +4,7 @@ namespace LiteNetLib { - internal sealed class NetConnectRequestPacket + public sealed class NetConnectRequestPacket { public const int HeaderSize = 18; public readonly long ConnectionTime; @@ -22,10 +22,10 @@ private NetConnectRequestPacket(long connectionTime, byte connectionNumber, int PeerId = localId; } - public static int GetProtocolId(NetPacket packet) => + internal static int GetProtocolId(NetPacket packet) => BitConverter.ToInt32(packet.RawData, 1); - public static NetConnectRequestPacket FromData(NetPacket packet) + internal static NetConnectRequestPacket FromData(NetPacket packet) { if (packet.ConnectionNumber >= NetConstants.MaxConnectionNumber) return null; @@ -51,7 +51,7 @@ public static NetConnectRequestPacket FromData(NetPacket packet) return new NetConnectRequestPacket(connectionTime, packet.ConnectionNumber, peerId, addressBytes, reader); } - public static NetPacket Make(ReadOnlySpan connectData, SocketAddress addressBytes, long connectTime, int localId) + internal static NetPacket Make(ReadOnlySpan connectData, SocketAddress addressBytes, long connectTime, int localId) { //Make initial packet var packet = new NetPacket(PacketProperty.ConnectRequest, connectData.Length+addressBytes.Size); diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 2426cb96..572fd105 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -78,7 +78,7 @@ private struct OutboundDelayedPacket private NetEvent _netEventPoolHead; private readonly ILiteNetEventListener _netEventListener; - private readonly Dictionary _requestsDict = new Dictionary(); + private readonly Dictionary _requestsDict = new Dictionary(); private long _connectedPeersCount; private readonly PacketLayerBase _extraPacketLayer; @@ -331,7 +331,7 @@ private void CreateEvent( SocketError errorCode = 0, int latency = 0, DisconnectReason disconnectReason = DisconnectReason.ConnectionFailed, - ConnectionRequest connectionRequest = null, + LiteConnectionRequest connectionRequest = null, DeliveryMethod deliveryMethod = DeliveryMethod.Unreliable, byte channelNumber = 0, NetPacket readerSource = null, @@ -589,14 +589,17 @@ protected virtual LiteNetPeer CreateOutgoingPeer(IPEndPoint remoteEndPoint, int new LiteNetPeer(this, remoteEndPoint, id, connectNum, connectData); //accept - protected virtual LiteNetPeer CreateIncomingPeer(ConnectionRequest request, int id) => + protected virtual LiteNetPeer CreateIncomingPeer(LiteConnectionRequest request, int id) => new LiteNetPeer(this, request, id); //reject protected virtual LiteNetPeer CreateRejectPeer(IPEndPoint remoteEndPoint, int id) => new LiteNetPeer(this, remoteEndPoint, id); - internal LiteNetPeer OnConnectionSolved(ConnectionRequest request, byte[] rejectData, int start, int length) + protected virtual LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket) => + new LiteConnectionRequest(remoteEndPoint, requestPacket, this); + + internal LiteNetPeer OnConnectionSolved(LiteConnectionRequest request, byte[] rejectData, int start, int length) { LiteNetPeer netPeer = null; @@ -688,7 +691,7 @@ private void ProcessConnectRequest( NetDebug.Write($"ConnectRequest Id: {connRequest.ConnectionTime}, EP: {remoteEndPoint}"); } - ConnectionRequest req; + LiteConnectionRequest req; lock (_requestsDict) { if (_requestsDict.TryGetValue(remoteEndPoint, out req)) @@ -696,7 +699,7 @@ private void ProcessConnectRequest( req.UpdateRequest(connRequest); return; } - req = new ConnectionRequest(remoteEndPoint, connRequest, this); + req = CreateConnectionRequest(remoteEndPoint, connRequest); _requestsDict.Add(remoteEndPoint, req); } NetDebug.Write($"[NM] Creating request event: {connRequest.ConnectionTime}"); diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 0292b619..7c1d86bb 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -404,7 +404,7 @@ internal LiteNetPeer(LiteNetManager netManager, IPEndPoint remoteEndPoint, int i } //"Accept" incoming constructor - internal LiteNetPeer(LiteNetManager netManager, ConnectionRequest request, int id) + internal LiteNetPeer(LiteNetManager netManager, LiteConnectionRequest request, int id) : this(netManager, request.RemoteEndPoint, id) { _connectTime = request.InternalPacket.ConnectionTime; diff --git a/LiteNetLib/NetEvent.cs b/LiteNetLib/NetEvent.cs index 6529b707..b54f60aa 100644 --- a/LiteNetLib/NetEvent.cs +++ b/LiteNetLib/NetEvent.cs @@ -31,7 +31,7 @@ public enum EType public int Latency; public SocketError ErrorCode; public DisconnectReason DisconnectReason; - public ConnectionRequest ConnectionRequest; + public LiteConnectionRequest ConnectionRequest; public DeliveryMethod DeliveryMethod; public byte ChannelNumber; public readonly NetPacketReader DataReader; diff --git a/LiteNetLib/NetManager.cs b/LiteNetLib/NetManager.cs index d9b89763..8ff80cfe 100644 --- a/LiteNetLib/NetManager.cs +++ b/LiteNetLib/NetManager.cs @@ -129,13 +129,17 @@ protected override LiteNetPeer CreateOutgoingPeer(IPEndPoint remoteEndPoint, int new NetPeer(this, remoteEndPoint, id, connectNum, connectData); //accept - protected override LiteNetPeer CreateIncomingPeer(ConnectionRequest request, int id) => + protected override LiteNetPeer CreateIncomingPeer(LiteConnectionRequest request, int id) => new NetPeer(this, request, id); //reject protected override LiteNetPeer CreateRejectPeer(IPEndPoint remoteEndPoint, int id) => new NetPeer(this, remoteEndPoint, id); + //connection request when you use Accept for getting NetPeer instead of LiteNetPeer + protected override LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket) => + new ConnectionRequest(remoteEndPoint, requestPacket, this); + protected override void ProcessEvent(NetEvent evt) { NetDebug.Write("[NM] Processing event: " + evt.Type); @@ -171,7 +175,7 @@ protected override void ProcessEvent(NetEvent evt) _netEventListener.OnNetworkLatencyUpdate(netPeer, evt.Latency); break; case NetEvent.EType.ConnectionRequest: - _netEventListener.OnConnectionRequest(evt.ConnectionRequest); + _netEventListener.OnConnectionRequest((ConnectionRequest)evt.ConnectionRequest); break; case NetEvent.EType.MessageDelivered: _netEventListener.OnMessageDelivered(netPeer, evt.UserData); diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index e441cc9a..fcc304c5 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -26,7 +26,7 @@ internal NetPeer(NetManager netManager, IPEndPoint remoteEndPoint, int id, byte _channels = new BaseChannel[netManager.ChannelsCount * NetConstants.ChannelTypeCount]; } - internal NetPeer(NetManager netManager, ConnectionRequest request, int id) : base(netManager, request, id) + internal NetPeer(NetManager netManager, LiteConnectionRequest request, int id) : base(netManager, request, id) { _channels = new BaseChannel[netManager.ChannelsCount * NetConstants.ChannelTypeCount]; } From 9a3f505716a9303de1885bfb6e127fa0c76dd70a Mon Sep 17 00:00:00 2001 From: RevenantX Date: Thu, 12 Mar 2026 09:37:43 +0200 Subject: [PATCH 109/200] fix dotnet test command when both frameworks runs in parallel --- LiteNetLib.Tests/CommunicationTest.cs | 12 +++++---- LiteNetLib.Tests/LiteCommunicationTest.cs | 12 +++++---- LiteNetLib.Tests/TestUtility/TestPorts.cs | 32 +++++++++++++++++++++++ 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 LiteNetLib.Tests/TestUtility/TestPorts.cs diff --git a/LiteNetLib.Tests/CommunicationTest.cs b/LiteNetLib.Tests/CommunicationTest.cs index 1ffce0e6..fcc8224f 100644 --- a/LiteNetLib.Tests/CommunicationTest.cs +++ b/LiteNetLib.Tests/CommunicationTest.cs @@ -30,7 +30,9 @@ public void TearDown() ManagerStack?.Dispose(); } - private const int DefaultPort = 9050; + private static readonly int DefaultPort = TestPorts.ForFramework(9050); + private static readonly int ReconnectPort = TestPorts.ForFramework(10123); + private static readonly int ReuseClientPort = TestPorts.ForFramework(9049); private const string DefaultAppKey = "test_server"; private static readonly byte[] DefaultAppKeyBytes = [12, 0, 116, 101, 115, 116, 95, 115, 101, 114, 118, 101, 114]; @@ -270,7 +272,7 @@ public void ReconnectTest() }; client.Stop(); - client.Start(10123); + client.Start(ReconnectPort); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (connectCount < 2) @@ -279,7 +281,7 @@ public void ReconnectTest() { client.Stop(); Thread.Sleep(500); - client.Start(10123); + client.Start(ReconnectPort); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); reconnected = true; } @@ -465,7 +467,7 @@ public void ConnectAfterDisconnectWithSamePort() EventBasedNetListener listener = new EventBasedNetListener(); NetManager client = new NetManager(listener, new Crc32cLayer()); - Assert.That(client.Start(9049), Is.True); + Assert.That(client.Start(ReuseClientPort), Is.True); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (server.ConnectedPeersCount != 1) { @@ -479,7 +481,7 @@ public void ConnectAfterDisconnectWithSamePort() { connected = true; }; - Assert.That(client.Start(9049), Is.True); + Assert.That(client.Start(ReuseClientPort), Is.True); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (!connected) diff --git a/LiteNetLib.Tests/LiteCommunicationTest.cs b/LiteNetLib.Tests/LiteCommunicationTest.cs index 2b08f7ef..608d655d 100644 --- a/LiteNetLib.Tests/LiteCommunicationTest.cs +++ b/LiteNetLib.Tests/LiteCommunicationTest.cs @@ -30,7 +30,9 @@ public void TearDown() ManagerStack?.Dispose(); } - private const int DefaultPort = 9050; + private static readonly int DefaultPort = TestPorts.ForFramework(9050); + private static readonly int ReconnectPort = TestPorts.ForFramework(10123); + private static readonly int ReuseClientPort = TestPorts.ForFramework(9049); private const string DefaultAppKey = "test_server"; private static readonly byte[] DefaultAppKeyBytes = [12, 0, 116, 101, 115, 116, 95, 115, 101, 114, 118, 101, 114]; @@ -270,7 +272,7 @@ public void ReconnectTest() }; client.Stop(); - client.Start(10123); + client.Start(ReconnectPort); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (connectCount < 2) @@ -279,7 +281,7 @@ public void ReconnectTest() { client.Stop(); Thread.Sleep(500); - client.Start(10123); + client.Start(ReconnectPort); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); reconnected = true; } @@ -465,7 +467,7 @@ public void ConnectAfterDisconnectWithSamePort() var listener = new EventBasedLiteNetListener(); var client = new LiteNetManager(listener, new Crc32cLayer()); - Assert.That(client.Start(9049), Is.True); + Assert.That(client.Start(ReuseClientPort), Is.True); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (server.ConnectedPeersCount != 1) { @@ -479,7 +481,7 @@ public void ConnectAfterDisconnectWithSamePort() { connected = true; }; - Assert.That(client.Start(9049), Is.True); + Assert.That(client.Start(ReuseClientPort), Is.True); client.Connect("127.0.0.1", DefaultPort, DefaultAppKey); while (!connected) diff --git a/LiteNetLib.Tests/TestUtility/TestPorts.cs b/LiteNetLib.Tests/TestUtility/TestPorts.cs new file mode 100644 index 00000000..70b63934 --- /dev/null +++ b/LiteNetLib.Tests/TestUtility/TestPorts.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.Versioning; + +namespace LiteNetLib.Tests.TestUtility +{ + internal static class TestPorts + { + private const int BaselineFrameworkMajor = 8; + private const int FrameworkPortBlockSize = 1000; + + public static int ForFramework(int basePort) + { + var frameworkAttribute = (TargetFrameworkAttribute)Attribute.GetCustomAttribute( + typeof(TestPorts).Assembly, + typeof(TargetFrameworkAttribute)); + + if (frameworkAttribute == null) + return basePort; + + const string versionMarker = "Version=v"; + var versionStart = frameworkAttribute.FrameworkName.IndexOf(versionMarker, StringComparison.Ordinal); + if (versionStart < 0) + return basePort; + + var versionText = frameworkAttribute.FrameworkName.Substring(versionStart + versionMarker.Length); + if (!Version.TryParse(versionText, out var version)) + return basePort; + + return basePort + Math.Max(0, version.Major - BaselineFrameworkMajor) * FrameworkPortBlockSize; + } + } +} From b7b1fe36672fb8a00ba75624f730f553d821c512 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Sat, 14 Mar 2026 01:46:52 +0300 Subject: [PATCH 110/200] Update NetDataReader.cs --- LiteNetLib/Utils/NetDataReader.cs | 64 +++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 745318f1..b8599e43 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -52,6 +52,14 @@ public int AvailableBytes get => _dataSize - _position; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void EnsureAvailable(int count) + { + if (count < 0 || count > AvailableBytes) + throw new InvalidOperationException( + $"Not enough data to read {count} byte(s). Position={_position}, DataSize={_dataSize}"); + } + public void SkipBytes(int count) => _position += count; public void SetPosition(int position) => _position = position; @@ -110,12 +118,14 @@ public IPEndPoint GetIPEndPoint() //IPv4 if (GetByte() == 0) { + EnsureAvailable(4); address = new IPAddress(new ReadOnlySpan(_data, _position, 4)); _position += 4; } //IPv6 else { + EnsureAvailable(16); address = new IPAddress(new ReadOnlySpan(_data, _position, 16)); _position += 16; } @@ -128,12 +138,12 @@ public IPEndPoint GetIPEndPoint() public void Get(out char result) => result = GetChar(); public void Get(out ushort result) => result = GetUShort(); public void Get(out short result) => result = GetShort(); - public void Get(out ulong result) => result = GetULong(); + public void Get(out ulong result) => result = GetULong(); public void Get(out long result) => result = GetLong(); public void Get(out uint result) => result = GetUInt(); public void Get(out int result) => result = GetInt(); public void Get(out double result) => result = GetDouble(); - public void Get(out float result) => result = GetFloat(); + public void Get(out float result) => result = GetFloat(); public void Get(out string result) => result = GetString(); public void Get(out string result, int maxLength) => result = GetString(maxLength); public void Get(out Guid result) => result = GetGuid(); @@ -146,10 +156,15 @@ public T[] GetArray(ushort size) { ushort length = BitConverter.ToUInt16(_data, _position); _position += 2; + + int byteLength = checked(length * size); + EnsureAvailable(byteLength); + T[] result = new T[length]; - length *= size; - Buffer.BlockCopy(_data, _position, result, 0, length); - _position += length; + if (byteLength > 0) + Buffer.BlockCopy(_data, _position, result, 0, byteLength); + + _position += byteLength; return result; } @@ -283,9 +298,13 @@ public string GetString(int maxLength) return string.Empty; int actualSize = size - 1; - string result = maxLength > 0 && NetDataWriter.uTF8Encoding.GetCharCount(_data, _position, actualSize) > maxLength ? - string.Empty : - NetDataWriter.uTF8Encoding.GetString(_data, _position, actualSize); + EnsureAvailable(actualSize); + + string result = maxLength > 0 && + NetDataWriter.uTF8Encoding.GetCharCount(_data, _position, actualSize) > maxLength + ? string.Empty + : NetDataWriter.uTF8Encoding.GetString(_data, _position, actualSize); + _position += actualSize; return result; } @@ -297,6 +316,8 @@ public string GetString() return string.Empty; int actualSize = size - 1; + EnsureAvailable(actualSize); + string result = NetDataWriter.uTF8Encoding.GetString(_data, _position, actualSize); _position += actualSize; return result; @@ -307,6 +328,9 @@ public string GetLargeString() int size = GetInt(); if (size <= 0) return string.Empty; + + EnsureAvailable(size); + string result = NetDataWriter.uTF8Encoding.GetString(_data, _position, size); _position += size; return result; @@ -314,6 +338,7 @@ public string GetLargeString() public Guid GetGuid() { + EnsureAvailable(16); var result = new Guid(_data.AsSpan(_position, 16)); _position += 16; return result; @@ -321,6 +346,7 @@ public Guid GetGuid() public ArraySegment GetBytesSegment(int count) { + EnsureAvailable(count); ArraySegment segment = new ArraySegment(_data, _position, count); _position += count; return segment; @@ -329,7 +355,7 @@ public ArraySegment GetBytesSegment(int count) public ArraySegment GetRemainingBytesSegment() { ArraySegment segment = new ArraySegment(_data, _position, AvailableBytes); - _position = _data.Length; + _position = _dataSize; return segment; } @@ -359,18 +385,20 @@ public byte[] GetRemainingBytes() { byte[] outgoingData = new byte[AvailableBytes]; Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes); - _position = _data.Length; + _position = _dataSize; return outgoingData; } public void GetBytes(byte[] destination, int start, int count) { + EnsureAvailable(count); Buffer.BlockCopy(_data, _position, destination, start, count); _position += count; } public void GetBytes(byte[] destination, int count) { + EnsureAvailable(count); Buffer.BlockCopy(_data, _position, destination, 0, count); _position += count; } @@ -404,9 +432,9 @@ public string PeekString(int maxLength) return string.Empty; int actualSize = size - 1; - return (maxLength > 0 && NetDataWriter.uTF8Encoding.GetCharCount(_data, _position + 2, actualSize) > maxLength) ? - string.Empty : - NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); + return (maxLength > 0 && NetDataWriter.uTF8Encoding.GetCharCount(_data, _position + 2, actualSize) > maxLength) + ? string.Empty + : NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); } public string PeekString() @@ -558,7 +586,9 @@ public bool TryGetString(out string result) if (AvailableBytes >= 2) { ushort strSize = PeekUShort(); - if (AvailableBytes >= strSize + 1) + int actualSize = strSize == 0 ? 0 : strSize - 1; + + if (AvailableBytes >= 2 + actualSize) { result = GetString(); return true; @@ -570,7 +600,8 @@ public bool TryGetString(out string result) public bool TryGetStringArray(out string[] result) { - if (!TryGetUShort(out ushort strArrayLength)) { + if (!TryGetUShort(out ushort strArrayLength)) + { result = null; return false; } @@ -593,7 +624,7 @@ public bool TryGetBytesWithLength(out byte[] result) if (AvailableBytes >= 2) { ushort length = PeekUShort(); - if (length >= 0 && AvailableBytes >= 2 + length) + if (AvailableBytes >= 2 + length) { result = GetBytesWithLength(); return true; @@ -607,6 +638,7 @@ public bool TryGetBytesWithLength(out byte[] result) public void Clear() { _position = 0; + _offset = 0; _dataSize = 0; _data = null; } From 0bdaf2843affc6b21dfc4ead1fcee1bf663123ed Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 18 Mar 2026 02:14:08 +0300 Subject: [PATCH 111/200] Improve fragment reassembly and timeout handling Add FragmentTimeout to LiteNetManager and refactor fragment reassembly logic to be safer and more memory-efficient. IncomingFragments now uses a small fixed array up to a threshold and a dictionary for larger fragment sets, tracks LastReceivedTime, and exposes helpers to Get/Set/Remove fragments and recycle packets. Added validation for FragmentsTotal/FragmentPart and metadata mismatches, an AbortReassembly helper to centralize cleanup, and more robust bounds/error checks. Maintain an _updateTime and purge expired fragment assemblies during Update to avoid stale fragments and leaks. --- LiteNetLib/LiteNetManager.cs | 5 + LiteNetLib/LiteNetPeer.cs | 172 +++++++++++++++++++++++++++-------- 2 files changed, 137 insertions(+), 40 deletions(-) diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 572fd105..85688933 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -205,6 +205,11 @@ private struct OutboundDelayedPacket /// public ushort MaxFragmentsCount = ushort.MaxValue; + /// + /// Fragmented packet timeout + /// + public ushort FragmentTimeout = 3000; + /// /// NatPunchModule for NAT hole punching operations /// diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 7c1d86bb..8d132121 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -100,12 +100,75 @@ private set //Fragment private class IncomingFragments { - public NetPacket[] Fragments; + // Fragments with TotalFragments <= threshold use a fixed array (faster) + // Larger sets use a dictionary to avoid large upfront allocations + private const int ArrayThreshold = 64; + + private readonly NetPacket[] _array; + private readonly Dictionary _dict; + + public readonly ushort TotalFragments; + public readonly byte ChannelId; public int ReceivedCount; public int TotalSize; - public byte ChannelId; + public float LastReceivedTime; + + public IncomingFragments(ushort totalFragments, byte channelId, float now) + { + TotalFragments = totalFragments; + ChannelId = channelId; + LastReceivedTime = now; + if (totalFragments <= ArrayThreshold) + _array = new NetPacket[totalFragments]; + else + _dict = new Dictionary(); + } + + public bool Contains(ushort part) => + _array != null ? _array[part] != null : _dict.ContainsKey(part); + + public bool TryGet(ushort part, out NetPacket packet) + { + if (_array != null) + { + packet = _array[part]; + return packet != null; + } + return _dict.TryGetValue(part, out packet); + } + + public void Set(ushort part, NetPacket packet) + { + if (_array != null) + _array[part] = packet; + else + _dict[part] = packet; + } + + public void Remove(ushort part) + { + if (_array != null) + _array[part] = null; + else + _dict.Remove(part); + } + + public void RecycleAll(LiteNetManager netManager) + { + if (_array != null) + { + foreach (var p in _array) + if (p != null) netManager.PoolRecycle(p); + } + else + { + foreach (var p in _dict.Values) + netManager.PoolRecycle(p); + } + } } private int _fragmentId; + private float _updateTime; private readonly Dictionary _holdedFragments; private readonly Dictionary _deliveredFragments; @@ -754,81 +817,90 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) { if (p.IsFragmented) { - if (p.FragmentsTotal > NetManager.MaxFragmentsCount) + 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; } + NetDebug.Write($"Fragment. Id: {p.FragmentId}, Part: {p.FragmentPart}, Total: {p.FragmentsTotal}"); - //Get needed array from dictionary + ushort packetFragId = p.FragmentId; byte packetChannelId = p.ChannelId; + if (!_holdedFragments.TryGetValue(packetFragId, out var incomingFragments)) { - //Holded fragments limit reached if (_holdedFragments.Count >= NetConstants.MaxFragmentsInWindow * ChannelsCount * NetConstants.FragmentedChannelsCount) { NetManager.PoolRecycle(p); - //NetDebug.WriteError($"Holded fragments limit reached ({_holdedFragments.Count}/{(NetConstants.DefaultWindowSize / 2) * ChannelsCount * NetConstants.FragmentedChannelsCount}). Dropping fragment id: {packetFragId}"); return; } - incomingFragments = new IncomingFragments - { - Fragments = new NetPacket[p.FragmentsTotal], - ChannelId = p.ChannelId - }; + incomingFragments = new IncomingFragments(p.FragmentsTotal, p.ChannelId, _updateTime); _holdedFragments.Add(packetFragId, incomingFragments); } + else if (p.FragmentsTotal != incomingFragments.TotalFragments || p.ChannelId != incomingFragments.ChannelId) + { + NetManager.PoolRecycle(p); + NetDebug.WriteError("Fragment metadata mismatch"); + return; + } - //Cache - var fragments = incomingFragments.Fragments; - - //Error check - if (p.FragmentPart >= fragments.Length || - fragments[p.FragmentPart] != null || - p.ChannelId != incomingFragments.ChannelId) + if (incomingFragments.Contains(p.FragmentPart)) { NetManager.PoolRecycle(p); - NetDebug.WriteError("Invalid fragment packet"); return; } - //Fill array - fragments[p.FragmentPart] = p; - //Increase received fragments count + incomingFragments.Set(p.FragmentPart, p); incomingFragments.ReceivedCount++; - - //Increase total size incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize; + incomingFragments.LastReceivedTime = _updateTime; - //Check for finish - if (incomingFragments.ReceivedCount != fragments.Length) + if (incomingFragments.ReceivedCount != incomingFragments.TotalFragments) return; - //just simple packet NetPacket resultingPacket = NetManager.PoolGetPacket(incomingFragments.TotalSize); + void AbortReassembly(string error) + { + _holdedFragments.Remove(packetFragId); + incomingFragments.RecycleAll(NetManager); + NetManager.PoolRecycle(resultingPacket); + NetDebug.WriteError(error); + } + int pos = 0; - for (int i = 0; i < incomingFragments.ReceivedCount; i++) + for (ushort i = 0; i < incomingFragments.TotalFragments; i++) { - var fragment = fragments[i]; + if (!incomingFragments.TryGet(i, out var fragment)) + { + AbortReassembly($"Fragment {i} missing during reassembly"); + return; + } + int writtenSize = fragment.Size - NetConstants.FragmentedHeaderTotalSize; - if (pos+writtenSize > resultingPacket.RawData.Length) + if (pos + writtenSize > resultingPacket.RawData.Length) { - _holdedFragments.Remove(packetFragId); - NetDebug.WriteError($"Fragment error pos: {pos + writtenSize} >= resultPacketSize: {resultingPacket.RawData.Length} , totalSize: {incomingFragments.TotalSize}"); + AbortReassembly($"Fragment error pos: {pos + writtenSize} >= resultPacketSize: {resultingPacket.RawData.Length}"); return; } + if (fragment.Size > fragment.RawData.Length) { - _holdedFragments.Remove(packetFragId); - NetDebug.WriteError($"Fragment error size: {fragment.Size} > fragment.RawData.Length: {fragment.RawData.Length}"); + AbortReassembly($"Fragment error size: {fragment.Size} > fragment.RawData.Length: {fragment.RawData.Length}"); return; } - //Create resulting big packet Buffer.BlockCopy( fragment.RawData, NetConstants.FragmentedHeaderTotalSize, @@ -837,15 +909,11 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) writtenSize); pos += writtenSize; - //Free memory NetManager.PoolRecycle(fragment); - fragments[i] = null; + incomingFragments.Remove(i); } - //Clear memory _holdedFragments.Remove(packetFragId); - - //Send to process NetManager.CreateReceiveEvent(resultingPacket, method, (byte)(packetChannelId / NetConstants.ChannelTypeCount), 0, this); } else //Just simple packet @@ -1154,6 +1222,8 @@ protected virtual void UpdateChannels() internal void Update(float deltaTime) { + _updateTime += deltaTime; + Interlocked.Exchange(ref _timeSinceLastPacket, _timeSinceLastPacket + deltaTime); switch (_connectionState) { @@ -1230,6 +1300,28 @@ internal void Update(float deltaTime) UpdateMtuLogic(deltaTime); + if (_holdedFragments.Count > 0) + { + List expired = null; + foreach (var kv in _holdedFragments) + { + if (_updateTime - kv.Value.LastReceivedTime > NetManager.FragmentTimeout) + { + expired ??= new List(); + expired.Add(kv.Key); + } + } + + if (expired != null) + { + foreach (ushort fragId in expired) + { + if (_holdedFragments.Remove(fragId, out var fragments)) + fragments.RecycleAll(NetManager); + } + } + } + UpdateChannels(); if (_unreliablePendingCount > 0) From 37eeabe960f1aac2b9fe421c3c074ae658e888b8 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 18 Mar 2026 23:55:02 +0300 Subject: [PATCH 112/200] Remove timeout --- LiteNetLib/LiteNetManager.cs | 5 ----- LiteNetLib/LiteNetPeer.cs | 32 ++------------------------------ 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 85688933..572fd105 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -205,11 +205,6 @@ private struct OutboundDelayedPacket ///
    public ushort MaxFragmentsCount = ushort.MaxValue; - /// - /// Fragmented packet timeout - /// - public ushort FragmentTimeout = 3000; - /// /// NatPunchModule for NAT hole punching operations /// diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 8d132121..96997b9e 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -111,13 +111,11 @@ private class IncomingFragments public readonly byte ChannelId; public int ReceivedCount; public int TotalSize; - public float LastReceivedTime; - public IncomingFragments(ushort totalFragments, byte channelId, float now) + public IncomingFragments(ushort totalFragments, byte channelId) { TotalFragments = totalFragments; ChannelId = channelId; - LastReceivedTime = now; if (totalFragments <= ArrayThreshold) _array = new NetPacket[totalFragments]; else @@ -168,7 +166,6 @@ public void RecycleAll(LiteNetManager netManager) } } private int _fragmentId; - private float _updateTime; private readonly Dictionary _holdedFragments; private readonly Dictionary _deliveredFragments; @@ -844,7 +841,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) return; } - incomingFragments = new IncomingFragments(p.FragmentsTotal, p.ChannelId, _updateTime); + incomingFragments = new IncomingFragments(p.FragmentsTotal, p.ChannelId); _holdedFragments.Add(packetFragId, incomingFragments); } else if (p.FragmentsTotal != incomingFragments.TotalFragments || p.ChannelId != incomingFragments.ChannelId) @@ -863,7 +860,6 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) incomingFragments.Set(p.FragmentPart, p); incomingFragments.ReceivedCount++; incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize; - incomingFragments.LastReceivedTime = _updateTime; if (incomingFragments.ReceivedCount != incomingFragments.TotalFragments) return; @@ -1222,8 +1218,6 @@ protected virtual void UpdateChannels() internal void Update(float deltaTime) { - _updateTime += deltaTime; - Interlocked.Exchange(ref _timeSinceLastPacket, _timeSinceLastPacket + deltaTime); switch (_connectionState) { @@ -1300,28 +1294,6 @@ internal void Update(float deltaTime) UpdateMtuLogic(deltaTime); - if (_holdedFragments.Count > 0) - { - List expired = null; - foreach (var kv in _holdedFragments) - { - if (_updateTime - kv.Value.LastReceivedTime > NetManager.FragmentTimeout) - { - expired ??= new List(); - expired.Add(kv.Key); - } - } - - if (expired != null) - { - foreach (ushort fragId in expired) - { - if (_holdedFragments.Remove(fragId, out var fragments)) - fragments.RecycleAll(NetManager); - } - } - } - UpdateChannels(); if (_unreliablePendingCount > 0) From 3645b3189b37d627e3dcc30361ea8cd848758e0a Mon Sep 17 00:00:00 2001 From: Alexander Fields Date: Wed, 18 Mar 2026 20:34:21 -0400 Subject: [PATCH 113/200] Add automated NuGet publishing workflow --- .github/workflows/nuget-publish.yml | 90 +++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 .github/workflows/nuget-publish.yml diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml new file mode 100644 index 00000000..afe7e34b --- /dev/null +++ b/.github/workflows/nuget-publish.yml @@ -0,0 +1,90 @@ +name: Publish NuGet Package + +on: + push: + branches: [ master ] + workflow_dispatch: + +jobs: + publish-release: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup .NET + uses: actions/setup-dotnet@v4 + with: + dotnet-version: 8.0.x + + - name: Restore dependencies + run: dotnet restore + + - name: Build LiteNetLib + run: dotnet build LiteNetLib/LiteNetLib.csproj --configuration Release + + - name: Check version and pack if changed + id: check-pack + run: | + echo "Checking for version changes..." + + PROJECT_PATH="LiteNetLib/LiteNetLib.csproj" + PACKAGE_NAME="litenetlib" + + # Extract version from project file + LOCAL_VERSION=$(grep -o '[^<]*' "$PROJECT_PATH" | sed 's/\(.*\)<\/Version>/\1/') + + if [ -z "$LOCAL_VERSION" ]; then + echo "No tag found in $PROJECT_PATH" + echo "has_packages=false" >> $GITHUB_OUTPUT + exit 0 + fi + + # Get the latest version from NuGet.org + echo "Checking NuGet.org for $PACKAGE_NAME..." + NUGET_VERSION=$(curl -s "https://api.nuget.org/v3-flatcontainer/$PACKAGE_NAME/index.json" | grep -o '"[^"]*"' | sed 's/"//g' | sort -V | tail -n 1) + + echo "Local version: $LOCAL_VERSION" + echo "NuGet version: $NUGET_VERSION" + + # Compare versions + if [ "$LOCAL_VERSION" != "$NUGET_VERSION" ]; then + echo "Version changed - will pack and publish" + mkdir -p ./nupkgs + dotnet pack "$PROJECT_PATH" --configuration Release --no-build --output ./nupkgs + echo "has_packages=true" >> $GITHUB_OUTPUT + else + echo "Version unchanged - skipping" + echo "has_packages=false" >> $GITHUB_OUTPUT + fi + + - name: Push to NuGet.org + if: steps.check-pack.outputs.has_packages == 'true' + env: + NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }} + run: | + echo "Publishing to NuGet.org..." + for package in ./nupkgs/*.nupkg; do + if [ -f "$package" ]; then + echo "Publishing $package..." + dotnet nuget push "$package" --api-key "$NUGET_API_KEY" --source https://api.nuget.org/v3/index.json --skip-duplicate || { + echo "Failed to publish $package" + exit 1 + } + fi + done + + - name: Upload package as artifact + if: steps.check-pack.outputs.has_packages == 'true' + uses: actions/upload-artifact@v4 + with: + name: nuget-package + path: ./nupkgs/*.nupkg + retention-days: 7 + + - name: No package to publish + if: steps.check-pack.outputs.has_packages == 'false' + run: echo "Version unchanged - nothing to publish" From aa637599103ad04b737a68bb4cdbf02126aed616 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:37:09 +0100 Subject: [PATCH 114/200] Update NetDataReader - Add documentation - Update methods to be faster --- LiteNetLib/Utils/NetDataReader.cs | 549 +++++++++++++++++++++++++----- 1 file changed, 468 insertions(+), 81 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index b8599e43..3271c064 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -1,57 +1,95 @@ using System; using System.Net; +using System.Net.Sockets; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace LiteNetLib.Utils { - public class NetDataReader + public unsafe class NetDataReader { protected byte[] _data; protected int _position; protected int _dataSize; protected int _offset; + /// + /// Gets the internal array containing the raw network data. + /// public byte[] RawData { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _data; } + + /// + /// Gets the total size of the buffer. + /// public int RawDataSize { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _dataSize; } + + /// + /// Gets the starting offset of the user payload within the . + /// public int UserDataOffset { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _offset; } + + /// + /// Gets the size of the user payload excluding the initial . + /// public int UserDataSize { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _dataSize - _offset; } + + /// + /// Gets a value indicating whether the internal data buffer is . + /// public bool IsNull { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _data == null; } + + /// + /// Gets the current read position within the buffer. + /// public int Position { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _position; } + + /// + /// Gets a value indicating whether the has reached the end of the data. + /// public bool EndOfData { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _position == _dataSize; } + + /// + /// Gets the number of s remaining to be read. + /// public int AvailableBytes { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _dataSize - _position; } + /// + /// Verifies that the buffer has at least s available to read. + /// + /// The number of s required. + /// Thrown if exceeds or is negative. [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EnsureAvailable(int count) { @@ -60,10 +98,22 @@ private void EnsureAvailable(int count) $"Not enough data to read {count} byte(s). Position={_position}, DataSize={_dataSize}"); } + /// + /// Advances the by the specified . + /// + /// The number of s to skip. public void SkipBytes(int count) => _position += count; + /// + /// Sets the current read to a specific index. + /// + /// The index to move the to. public void SetPosition(int position) => _position = position; + /// + /// Reinitializes the reader using data from a . + /// + /// The source . public void SetSource(NetDataWriter dataWriter) { _data = dataWriter.Data; @@ -72,6 +122,10 @@ public void SetSource(NetDataWriter dataWriter) _dataSize = dataWriter.Length; } + /// + /// Reinitializes the reader using a array. + /// + /// The source array. public void SetSource(byte[] source) { _data = source; @@ -80,6 +134,12 @@ public void SetSource(byte[] source) _dataSize = source.Length; } + /// + /// Reinitializes the reader using a segment of a array. + /// + /// The source array. + /// The starting index for reading. + /// The total number of s available to read from the . public void SetSource(byte[] source, int offset, int maxSize) { _data = source; @@ -98,20 +158,43 @@ public NetDataReader() { } #region GetMethods + /// + /// Deserializes a that implements . + /// + /// A type implementing . + /// The deserialized output. public void Get(out T result) where T : struct, INetSerializable { - result = default(T); + result = default; result.Deserialize(this); } + /// + /// Deserializes a that implements using a provided constructor. + /// + /// A type implementing . + /// The deserialized instance output. + /// A factory used to instantiate the . public void Get(out T result, Func constructor) where T : class, INetSerializable { result = constructor(); result.Deserialize(this); } + /// + /// Deserializes an and assigns it to the parameter. + /// + /// The deserialized output. public void Get(out IPEndPoint result) => result = GetIPEndPoint(); + /// + /// Reads an from the current . + /// + /// The deserialized . + /// + /// Reads a to determine the (0 for IPv4, 1 for IPv6), + /// followed by the address bytes and a 2-byte port. + /// public IPEndPoint GetIPEndPoint() { IPAddress address; @@ -132,30 +215,82 @@ public IPEndPoint GetIPEndPoint() return new IPEndPoint(address, GetUShort()); } + /// Reads a and assigns it to . public void Get(out byte result) => result = GetByte(); + + /// Reads an and assigns it to . public void Get(out sbyte result) => result = (sbyte)GetByte(); + + /// Reads a and assigns it to . public void Get(out bool result) => result = GetBool(); + + /// Reads a and assigns it to . public void Get(out char result) => result = GetChar(); + + /// Reads a and assigns it to . public void Get(out ushort result) => result = GetUShort(); + + /// Reads a and assigns it to . public void Get(out short result) => result = GetShort(); + + /// Reads a and assigns it to . public void Get(out ulong result) => result = GetULong(); + + /// Reads a and assigns it to . public void Get(out long result) => result = GetLong(); + + /// Reads a and assigns it to . public void Get(out uint result) => result = GetUInt(); + + /// Reads an and assigns it to . public void Get(out int result) => result = GetInt(); + + /// Reads a and assigns it to . public void Get(out double result) => result = GetDouble(); + + /// Reads a and assigns it to . public void Get(out float result) => result = GetFloat(); + + /// Reads a and assigns it to . public void Get(out string result) => result = GetString(); + + /// Reads a with a length limit and assigns it to . public void Get(out string result, int maxLength) => result = GetString(maxLength); + + /// Reads a and assigns it to . public void Get(out Guid result) => result = GetGuid(); + /// Reads the next from the buffer. public byte GetByte() => _data[_position++]; + /// Reads the next from the buffer. public sbyte GetSByte() => (sbyte)GetByte(); + /// + /// Reads an array of unmanaged values prefixed by a length. + /// + /// An unmanaged type. + /// A new array of type . + public T[] GetUnmanagedArray() where T : unmanaged + { + ushort length = GetUShort(); + int byteLength = length * sizeof(T); + ReadOnlySpan slice = _data.AsSpan(_position, byteLength); + T[] result = MemoryMarshal.Cast(slice) + .ToArray(); + _position += byteLength; + return result; + } + + /// + /// Reads an array of values by performing a direct memory copy. + /// + /// The element type. + /// The size of a single element in s. + /// A new array of type . public T[] GetArray(ushort size) { - ushort length = BitConverter.ToUInt16(_data, _position); - _position += 2; + ushort length = GetUShort(); int byteLength = checked(length * size); EnsureAvailable(byteLength); @@ -168,10 +303,14 @@ public T[] GetArray(ushort size) return result; } + /// + /// Reads an array of objects implementing . + /// + /// A type with a parameterless constructor implementing . + /// A new array of type . public T[] GetArray() where T : INetSerializable, new() { - ushort length = BitConverter.ToUInt16(_data, _position); - _position += 2; + ushort length = GetUShort(); T[] result = new T[length]; for (int i = 0; i < length; i++) { @@ -182,26 +321,55 @@ public T[] GetArray(ushort size) return result; } + /// + /// Reads an array of objects implementing using a specific constructor. + /// + /// A type implementing . + /// The factory used to create instances. + /// A new array of type . public T[] GetArray(Func constructor) where T : class, INetSerializable { - ushort length = BitConverter.ToUInt16(_data, _position); - _position += 2; + ushort length = GetUShort(); T[] result = new T[length]; for (int i = 0; i < length; i++) Get(out result[i], constructor); return result; } - public bool[] GetBoolArray() => GetArray(1); - public ushort[] GetUShortArray() => GetArray(2); - public short[] GetShortArray() => GetArray(2); - public int[] GetIntArray() => GetArray(4); - public uint[] GetUIntArray() => GetArray(4); - public float[] GetFloatArray() => GetArray(4); - public double[] GetDoubleArray() => GetArray(8); - public long[] GetLongArray() => GetArray(8); - public ulong[] GetULongArray() => GetArray(8); + /// Reads an array of values. + public bool[] GetBoolArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public ushort[] GetUShortArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public short[] GetShortArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public int[] GetIntArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public uint[] GetUIntArray() => GetUnmanagedArray(); + /// Reads an array of values. + public float[] GetFloatArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public double[] GetDoubleArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public long[] GetLongArray() => GetUnmanagedArray(); + + /// Reads an array of values. + public ulong[] GetULongArray() => GetUnmanagedArray(); + + /// + /// Reads an array of values. + /// + /// A new array. + /// + /// Reads a 2-byte length header followed by each element. + /// public string[] GetStringArray() { ushort length = GetUShort(); @@ -214,9 +382,13 @@ public string[] GetStringArray() } /// - /// Note that "maxStringLength" only limits the number of characters in a string, not its size in bytes. - /// Strings that exceed this parameter are returned as empty + /// Reads an array of values with a maximum character limit per element. /// + /// The maximum number of characters allowed per . + /// A new array. + /// + /// Strings exceeding are returned as . + /// public string[] GetStringArray(int maxStringLength) { ushort length = GetUShort(); @@ -228,69 +400,45 @@ public string[] GetStringArray(int maxStringLength) return arr; } + /// Reads a value from the current position. + /// if the byte is 1; otherwise, . public bool GetBool() => GetByte() == 1; + + /// Reads a value as a 2-byte . public char GetChar() => (char)GetUShort(); - public ushort GetUShort() - { - ushort result = BitConverter.ToUInt16(_data, _position); - _position += 2; - return result; - } + /// Reads a value using unmanaged memory access. + public ushort GetUShort() => GetUnmanaged(); - public short GetShort() - { - short result = BitConverter.ToInt16(_data, _position); - _position += 2; - return result; - } + /// Reads a value using unmanaged memory access. + public short GetShort() => GetUnmanaged(); - public long GetLong() - { - long result = BitConverter.ToInt64(_data, _position); - _position += 8; - return result; - } + /// Reads a value using unmanaged memory access. + public long GetLong() => GetUnmanaged(); - public ulong GetULong() - { - ulong result = BitConverter.ToUInt64(_data, _position); - _position += 8; - return result; - } + /// Reads a value using unmanaged memory access. + public ulong GetULong() => GetUnmanaged(); - public int GetInt() - { - int result = BitConverter.ToInt32(_data, _position); - _position += 4; - return result; - } + /// Reads an value using unmanaged memory access. + public int GetInt() => GetUnmanaged(); - public uint GetUInt() - { - uint result = BitConverter.ToUInt32(_data, _position); - _position += 4; - return result; - } + /// Reads a value using unmanaged memory access. + public uint GetUInt() => GetUnmanaged(); - public float GetFloat() - { - float result = BitConverter.ToSingle(_data, _position); - _position += 4; - return result; - } + /// Reads a value using unmanaged memory access. + public float GetFloat() => GetUnmanaged(); - public double GetDouble() - { - double result = BitConverter.ToDouble(_data, _position); - _position += 8; - return result; - } + /// Reads a value using unmanaged memory access. + public double GetDouble() => GetUnmanaged(); /// - /// Note that "maxLength" only limits the number of characters in a string, not its size in bytes. + /// Reads a with a maximum character limit. /// - /// "string.Empty" if value > "maxLength" + /// The maximum allowed character count. + /// The deserialized , or if the character count exceeds . + /// + /// Note that limits the number of characters, not the total size in s. + /// public string GetString(int maxLength) { ushort size = GetUShort(); @@ -309,6 +457,10 @@ public string GetString(int maxLength) return result; } + /// + /// Reads a from the current position. + /// + /// The deserialized . public string GetString() { ushort size = GetUShort(); @@ -323,6 +475,10 @@ public string GetString() return result; } + /// + /// Reads a prefixed with a 4-byte length header. + /// + /// The deserialized . public string GetLargeString() { int size = GetInt(); @@ -336,6 +492,10 @@ public string GetLargeString() return result; } + /// + /// Reads a 16-byte . + /// + /// The deserialized . public Guid GetGuid() { EnsureAvailable(16); @@ -344,6 +504,11 @@ public Guid GetGuid() return result; } + /// + /// Gets an of s from the current position. + /// + /// The number of s to include in the segment. + /// An wrapping the internal buffer. public ArraySegment GetBytesSegment(int count) { EnsureAvailable(count); @@ -352,6 +517,10 @@ public ArraySegment GetBytesSegment(int count) return segment; } + /// + /// Gets an containing all remaining s. + /// + /// An from the current position to the end of the data. public ArraySegment GetRemainingBytesSegment() { ArraySegment segment = new ArraySegment(_data, _position, AvailableBytes); @@ -359,6 +528,11 @@ public ArraySegment GetRemainingBytesSegment() return segment; } + /// + /// Deserializes a that implements . + /// + /// A type implementing . + /// The deserialized . public T Get() where T : struct, INetSerializable { var obj = default(T); @@ -366,6 +540,12 @@ public T Get() where T : struct, INetSerializable return obj; } + /// + /// Deserializes a that implements using a provided constructor. + /// + /// A type implementing . + /// The factory used to instantiate the . + /// A new instance of . public T Get(Func constructor) where T : class, INetSerializable { var obj = constructor(); @@ -373,14 +553,29 @@ public T Get(Func constructor) where T : class, INetSerializable return obj; } + /// + /// Returns a of s containing all remaining data. + /// + /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan GetRemainingBytesSpan() => new ReadOnlySpan(_data, _position, _dataSize - _position); + /// + /// Returns a of s containing all remaining data. + /// + /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory GetRemainingBytesMemory() => new ReadOnlyMemory(_data, _position, _dataSize - _position); + /// + /// Reads all remaining s and returns them as a new array. + /// + /// A new array containing the remaining data. + /// + /// This method performs a heap allocation and advances the to the end of the data. + /// public byte[] GetRemainingBytes() { byte[] outgoingData = new byte[AvailableBytes]; @@ -389,6 +584,12 @@ public byte[] GetRemainingBytes() return outgoingData; } + /// + /// Copies a specified number of s into a destination array at a specific offset. + /// + /// The array to copy data into. + /// The starting index in the array. + /// The number of s to read. public void GetBytes(byte[] destination, int start, int count) { EnsureAvailable(count); @@ -396,6 +597,11 @@ public void GetBytes(byte[] destination, int start, int count) _position += count; } + /// + /// Copies a specified number of s into a destination array starting at index 0. + /// + /// The array to copy data into. + /// The number of s to read. public void GetBytes(byte[] destination, int count) { EnsureAvailable(count); @@ -403,28 +609,140 @@ public void GetBytes(byte[] destination, int count) _position += count; } - public sbyte[] GetSBytesWithLength() => GetArray(1); - public byte[] GetBytesWithLength() => GetArray(1); + /// + /// Reads an array prefixed with its length. + /// + /// A new array. + public sbyte[] GetSBytesWithLength() => GetUnmanagedArray(); + + /// + /// Reads a array prefixed with its length. + /// + /// A new array. + public byte[] GetBytesWithLength() => GetUnmanagedArray(); + + /// + /// Reads a value of type from the internal byte buffer at the current position, + /// advancing the position by the size of . + /// + /// An unmanaged value type to read from the buffer. + /// The value of type read from the buffer. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T GetUnmanaged() where T : unmanaged + { + var size = sizeof(T); + EnsureAvailable(size); + +#if NET8_0_OR_GREATER + var value = Unsafe.ReadUnaligned(ref _data[_position]); +#else + T value; + fixed (byte* ptr = &_data[_position]) + { + value = *(T*)ptr; + } +#endif + + _position += size; + return value; + } + + /// + /// Reads a nullable value of type from the internal byte buffer at the current position, + /// first reading a indicating whether the value is present, + /// and then reading the value itself if it exists.
    + /// Advances the position by 1 byte for the presence flag plus the size of if the value is present. + ///
    + /// An unmanaged value type to read from the buffer. + /// + /// The nullable value of type read from the buffer. + /// Returns if the presence flag indicates no value. + /// + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T? GetNullableUnmanaged() where T : unmanaged + { + var hasValue = GetBool(); + if (!hasValue) + { + return null; + } + + return GetUnmanaged(); + } + + /// + /// Reads an enum value of type from the internal data buffer at the current position.
    + /// Advances the position by the size of . + ///
    + /// An unmanaged enum type to read. + /// The enum value read from the buffer. + public T GetEnum() where T : unmanaged, Enum + { + var span = GetSpan(sizeof(T)); +#if NET8_0_OR_GREATER + return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(span)); +#else + fixed (byte* ptr = span) + { + return *(T*)ptr; + } +#endif + } + + public ReadOnlySpan GetSpan(int length) + { + ReadOnlySpan span = new ReadOnlySpan(_data, _position, length); + _position += length; + return span; + } + #endregion #region PeekMethods + /// Reads the at the current position without advancing the . public byte PeekByte() => _data[_position]; + + /// Reads the at the current position without advancing the . public sbyte PeekSByte() => (sbyte)_data[_position]; + + /// Reads the at the current position without advancing the . public bool PeekBool() => _data[_position] == 1; - public char PeekChar() => (char)PeekUShort(); - public ushort PeekUShort() => BitConverter.ToUInt16(_data, _position); - public short PeekShort() => BitConverter.ToInt16(_data, _position); - public long PeekLong() => BitConverter.ToInt64(_data, _position); - public ulong PeekULong() => BitConverter.ToUInt64(_data, _position); - public int PeekInt() => BitConverter.ToInt32(_data, _position); - public uint PeekUInt() => BitConverter.ToUInt32(_data, _position); - public float PeekFloat() => BitConverter.ToSingle(_data, _position); - public double PeekDouble() => BitConverter.ToDouble(_data, _position); + + /// Reads the at the current position without advancing the . + public char PeekChar() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public ushort PeekUShort() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public short PeekShort() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public long PeekLong() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public ulong PeekULong() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public int PeekInt() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public uint PeekUInt() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public float PeekFloat() => PeekUnmanaged(); + + /// Reads the at the current position without advancing the . + public double PeekDouble() => PeekUnmanaged(); /// - /// Note that "maxLength" only limits the number of characters in a string, not its size in bytes. + /// Reads a with a character limit without advancing the . /// + /// Maximum allowed character count. + /// Strings exceeding are returned as . public string PeekString(int maxLength) { ushort size = PeekUShort(); @@ -437,6 +755,9 @@ public string PeekString(int maxLength) : NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); } + /// + /// Reads a without advancing the . + /// public string PeekString() { ushort size = PeekUShort(); @@ -446,9 +767,32 @@ public string PeekString() int actualSize = size - 1; return NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); } + + /// + /// Reads an unmanaged value of type at the current position without advancing the . + /// + /// An unmanaged value type. + /// The value read from the buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T PeekUnmanaged() where T : unmanaged + { +#if NET8_0_OR_GREATER + return Unsafe.ReadUnaligned(ref _data[_position]); +#else + T value; + fixed (byte* ptr = &_data[_position]) + { + value = *(T*)ptr; + } + return value; +#endif + } #endregion #region TryGetMethods + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetByte(out byte result) { if (AvailableBytes >= 1) @@ -460,6 +804,9 @@ public bool TryGetByte(out byte result) return false; } + /// Attempts to read an without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetSByte(out sbyte result) { if (AvailableBytes >= 1) @@ -471,6 +818,9 @@ public bool TryGetSByte(out sbyte result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or if failed. + /// if enough data was available; otherwise, . public bool TryGetBool(out bool result) { if (AvailableBytes >= 1) @@ -482,6 +832,9 @@ public bool TryGetBool(out bool result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or '\0' if failed. + /// if enough data was available; otherwise, . public bool TryGetChar(out char result) { if (!TryGetUShort(out ushort uShortValue)) @@ -493,6 +846,9 @@ public bool TryGetChar(out char result) return true; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetShort(out short result) { if (AvailableBytes >= 2) @@ -504,6 +860,9 @@ public bool TryGetShort(out short result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetUShort(out ushort result) { if (AvailableBytes >= 2) @@ -515,6 +874,9 @@ public bool TryGetUShort(out ushort result) return false; } + /// Attempts to read an without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetInt(out int result) { if (AvailableBytes >= 4) @@ -526,6 +888,9 @@ public bool TryGetInt(out int result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetUInt(out uint result) { if (AvailableBytes >= 4) @@ -537,6 +902,9 @@ public bool TryGetUInt(out uint result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetLong(out long result) { if (AvailableBytes >= 8) @@ -548,6 +916,9 @@ public bool TryGetLong(out long result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetULong(out ulong result) { if (AvailableBytes >= 8) @@ -559,6 +930,9 @@ public bool TryGetULong(out ulong result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetFloat(out float result) { if (AvailableBytes >= 4) @@ -570,6 +944,9 @@ public bool TryGetFloat(out float result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. + /// if enough data was available; otherwise, . public bool TryGetDouble(out double result) { if (AvailableBytes >= 8) @@ -581,6 +958,9 @@ public bool TryGetDouble(out double result) return false; } + /// Attempts to read a without throwing an exception. + /// The deserialized , or if failed. + /// if enough data was available; otherwise, . public bool TryGetString(out string result) { if (AvailableBytes >= 2) @@ -598,6 +978,9 @@ public bool TryGetString(out string result) return false; } + /// Attempts to read a array without throwing an exception. + /// The deserialized array, or if failed. + /// if enough data was available; otherwise, . public bool TryGetStringArray(out string[] result) { if (!TryGetUShort(out ushort strArrayLength)) @@ -619,6 +1002,9 @@ public bool TryGetStringArray(out string[] result) return true; } + /// Attempts to read a array with a length header without throwing an exception. + /// The deserialized array, or if failed. + /// if enough data was available; otherwise, . public bool TryGetBytesWithLength(out byte[] result) { if (AvailableBytes >= 2) @@ -635,6 +1021,7 @@ public bool TryGetBytesWithLength(out byte[] result) } #endregion + /// Clears the reader state and releases the reference to the internal buffer. public void Clear() { _position = 0; From bbaf4b43c9fc3f28c1f10e597ec09bd848778c84 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:37:16 +0100 Subject: [PATCH 115/200] Update NetDataWriter - Add documentation - Update methods to be faster --- LiteNetLib/Utils/NetDataWriter.cs | 498 ++++++++++++++++++++++++------ 1 file changed, 403 insertions(+), 95 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index ada5c6e5..0849c0a3 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -2,33 +2,59 @@ using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; namespace LiteNetLib.Utils { - public class NetDataWriter + public unsafe class NetDataWriter { protected byte[] _data; protected int _position; private const int InitialSize = 64; private readonly bool _autoResize; + /// + /// Gets the total capacity of the internal buffer. + /// + /// The length of the underlying array. public int Capacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _data.Length; } + + /// + /// Gets the underlying array used by this writer. + /// + /// The internal array. + /// + /// Accessing this directly allows for external manipulation but bypasses bounds checking. + /// public byte[] Data { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _data; } + + /// + /// Gets the current number of s written to the buffer. + /// + /// The current . public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _position; } + /// + /// Returns a representing the currently used portion of the internal buffer. + /// + /// A from index 0 to . + /// + /// Provides a high-performance, zero-allocation view of the data. + /// The span becomes invalid if the internal buffer is resized or if changes. + /// public ReadOnlySpan AsReadOnlySpan() => new ReadOnlySpan(_data, 0, _position); internal static readonly UTF8Encoding uTF8Encoding = new UTF8Encoding(false, true); @@ -82,6 +108,11 @@ public static NetDataWriter FromBytes(Span bytes) return netDataWriter; } + /// + /// Creates a new and serializes a into it. + /// + /// The to serialize. + /// A new instance containing the serialized . public static NetDataWriter FromString(string value) { var netDataWriter = new NetDataWriter(); @@ -89,6 +120,14 @@ public static NetDataWriter FromString(string value) return netDataWriter; } + /// + /// Ensures the internal buffer is at least . + /// + /// The required minimum size of the buffer. + /// + /// If an allocation is necessary, the buffer grows to either + /// or doubles its current size, whichever is larger. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ResizeIfNeed(int newSize) { @@ -98,6 +137,14 @@ public void ResizeIfNeed(int newSize) } } + /// + /// Ensures the internal buffer can accommodate more s. + /// + /// The number of additional s to fit. + /// + /// This checks against the current . If the capacity is insufficient, + /// the buffer grows to either the required size or doubles its current size. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureFit(int additionalSize) { @@ -107,14 +154,32 @@ public void EnsureFit(int additionalSize) } } + + /// + /// Resets the to 0 and ensures the internal buffer has at least the specified . + /// + /// The minimum capacity required for the internal buffer. + /// + /// If the current buffer is smaller than , will allocate a larger array. + /// public void Reset(int size) { ResizeIfNeed(size); _position = 0; } + /// + /// Resets the to 0, effectively clearing the buffer for reuse. + /// public void Reset() => _position = 0; + /// + /// Creates a array containing the current data from the internal buffer. + /// + /// A new array of length . + /// + /// This method performs a heap allocation and copies the data using . + /// public byte[] CopyData() { byte[] resultData = new byte[_position]; @@ -134,88 +199,76 @@ public int SetPosition(int position) return prevPosition; } - public void Put(float value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(float value) => PutUnmanaged(value); - public void Put(double value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(double value) => PutUnmanaged(value); - public void Put(long value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(long value) => PutUnmanaged(value); - public void Put(ulong value) - { - if (_autoResize) - ResizeIfNeed(_position + 8); - FastBitConverter.GetBytes(_data, _position, value); - _position += 8; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(ulong value) => PutUnmanaged(value); - public void Put(int value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } + /// + /// Serializes an value. + /// + /// The value to write. + public void Put(int value) => PutUnmanaged(value); - public void Put(uint value) - { - if (_autoResize) - ResizeIfNeed(_position + 4); - FastBitConverter.GetBytes(_data, _position, value); - _position += 4; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(uint value) => PutUnmanaged(value); + /// + /// Serializes a value as a . + /// + /// The value to write. public void Put(char value) => Put((ushort)value); - public void Put(ushort value) - { - if (_autoResize) - ResizeIfNeed(_position + 2); - FastBitConverter.GetBytes(_data, _position, value); - _position += 2; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(ushort value) => PutUnmanaged(value); - public void Put(short value) - { - if (_autoResize) - ResizeIfNeed(_position + 2); - FastBitConverter.GetBytes(_data, _position, value); - _position += 2; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(short value) => PutUnmanaged(value); - public void Put(sbyte value) - { - if (_autoResize) - ResizeIfNeed(_position + 1); - _data[_position] = (byte)value; - _position++; - } + /// + /// Serializes an value. + /// + /// The value to write. + public void Put(sbyte value) => PutUnmanaged(value); - public void Put(byte value) - { - if (_autoResize) - ResizeIfNeed(_position + 1); - _data[_position] = value; - _position++; - } + /// + /// Serializes a value. + /// + /// The value to write. + public void Put(byte value) => PutUnmanaged(value); + /// + /// Serializes a value. + /// + /// The value to write. public void Put(Guid value) { if (_autoResize) @@ -224,22 +277,30 @@ public void Put(Guid value) _position += 16; } + /// + /// Serializes a segment of a array. + /// + /// The source array. + /// The starting index in the source array. + /// The number of s to write. public void Put(byte[] data, int offset, int length) { - if (_autoResize) - ResizeIfNeed(_position + length); - Buffer.BlockCopy(data, offset, _data, _position, length); - _position += length; + Put(data.AsSpan(offset, length)); } + /// + /// Serializes an entire array. + /// + /// The source array. public void Put(byte[] data) { - if (_autoResize) - ResizeIfNeed(_position + data.Length); - Buffer.BlockCopy(data, 0, _data, _position, data.Length); - _position += data.Length; + Put(data.AsSpan()); } + /// + /// Serializes a of s to the internal buffer. + /// + /// The span of data to write. public void Put(ReadOnlySpan data) { if (_autoResize) @@ -248,33 +309,99 @@ public void Put(ReadOnlySpan data) _position += data.Length; } + /// + /// Serializes a segment of an array prefixed with its length. + /// + /// The source array. + /// The starting index in the source array. + /// The number of elements to write. public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) { if (_autoResize) + { ResizeIfNeed(_position + 2 + length); - FastBitConverter.GetBytes(_data, _position, length); - Buffer.BlockCopy(data, offset, _data, _position + 2, length); - _position += 2 + length; + } + +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref _data[_position], length); +#else + fixed (byte* ptr = &_data[_position]) + { + *(ushort*)ptr = length; + } +#endif + _position += 2; + + if (length > 0) + { + ReadOnlySpan source = data.AsSpan(offset, length); + ReadOnlySpan sourceBytes = MemoryMarshal.Cast(source); + + sourceBytes.CopyTo(_data.AsSpan(_position)); + _position += length; + } } + /// + /// Serializes an array prefixed with its length. + /// + /// The source array. public void PutSBytesWithLength(sbyte[] data) => PutArray(data, 1); + /// + /// Serializes a segment of a array prefixed with its length. + /// + /// The source array. + /// The starting index in the source array. + /// The number of s to write. public void PutBytesWithLength(byte[] data, int offset, ushort length) { if (_autoResize) + { ResizeIfNeed(_position + 2 + length); - FastBitConverter.GetBytes(_data, _position, length); - Buffer.BlockCopy(data, offset, _data, _position + 2, length); - _position += 2 + length; + } + +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref _data[_position], length); +#else + fixed (byte* ptr = &_data[_position]) + { + *(ushort*)ptr = length; + } +#endif + _position += 2; + + if (length > 0) + { + data.AsSpan(offset, length).CopyTo(_data.AsSpan(_position)); + _position += length; + } } + /// + /// Serializes a array prefixed with its length. + /// + /// The source array. public void PutBytesWithLength(byte[] data) => PutArray(data, 1); + /// + /// Serializes a value as a single . + /// + /// The value to write. public void Put(bool value) => Put((byte)(value ? 1 : 0)); + /// + /// Serializes an prefixed with a 2-byte length. + /// + /// The source array to serialize. + /// The size of a single element in s. + /// + /// If the array is , a length of 0 is written.
    + /// The total payload size is calculated as length * sz. + ///
    public void PutArray(Array arr, int sz) { - ushort length = arr == null ? (ushort) 0 : (ushort)arr.Length; + ushort length = arr == null ? (ushort)0 : (ushort)arr.Length; sz *= length; if (_autoResize) ResizeIfNeed(_position + sz + 2); @@ -284,16 +411,89 @@ public void PutArray(Array arr, int sz) _position += sz + 2; } - public void PutArray(float[] value) => PutArray(value, 4); - public void PutArray(double[] value) => PutArray(value, 8); - public void PutArray(long[] value) => PutArray(value, 8); - public void PutArray(ulong[] value) => PutArray(value, 8); - public void PutArray(int[] value) => PutArray(value, 4); - public void PutArray(uint[] value) => PutArray(value, 4); - public void PutArray(ushort[] value) => PutArray(value, 2); - public void PutArray(short[] value) => PutArray(value, 2); - public void PutArray(bool[] value) => PutArray(value, 1); + /// + /// Serializes an array of unmanaged values. + /// + /// The unmanaged type of the array elements. + /// The array to serialize. + public void PutUnmanagedArray(T[] arr) where T : unmanaged + { + PutSpan(arr.AsSpan()); + } + + /// + /// Serializes a of unmanaged values to the internal buffer. + /// + /// The unmanaged type of the span elements. + /// The span of data to write. + /// + /// Writes a 2-byte length header followed by the raw binary data.
    + ///
    + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PutSpan(Span span) where T : unmanaged + { + var length = (ushort)span.Length; + var byteLength = length * sizeof(T); + + if (_autoResize) + { + ResizeIfNeed(_position + byteLength + 2); + } + +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref _data[_position], length); +#else + fixed (byte* ptr = &_data[_position]) + { + *(ushort*)ptr = length; + } +#endif + _position += 2; + + if (length > 0) + { + var sourceBytes = MemoryMarshal.AsBytes(span); + sourceBytes.CopyTo(_data.AsSpan(_position)); + _position += byteLength; + } + } + + /// + /// Serializes an array of unmanaged values to the internal buffer. + /// + public void PutArray(float[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(double[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(long[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(ulong[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(int[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(uint[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(ushort[] value) => PutUnmanagedArray(value); + + /// + public void PutArray(short[] value) => PutUnmanagedArray(value); + /// + public void PutArray(bool[] value) => PutUnmanagedArray(value); + + /// + /// Serializes an array of values. + /// + /// The array of elements to write. + /// + /// Writes a 2-byte length header followed by each element. + /// public void PutArray(string[] value) { ushort strArrayLength = value == null ? (ushort)0 : (ushort)value.Length; @@ -302,6 +502,11 @@ public void PutArray(string[] value) Put(value[i]); } + /// + /// Serializes an array of values with a maximum length constraint per element. + /// + /// The array of elements to write. + /// The maximum allowed length for each individual . public void PutArray(string[] value, int strMaxLength) { ushort strArrayLength = value == null ? (ushort)0 : (ushort)value.Length; @@ -310,6 +515,11 @@ public void PutArray(string[] value, int strMaxLength) Put(value[i], strMaxLength); } + /// + /// Serializes an array of objects implementing . + /// + /// A type that implements and has a parameterless constructor. + /// The array of objects to serialize. public void PutArray(T[] value) where T : INetSerializable, new() { ushort strArrayLength = (ushort)(value?.Length ?? 0); @@ -318,6 +528,14 @@ public void PutArray(string[] value, int strMaxLength) value[i].Serialize(this); } + /// + /// Serializes an . + /// + /// The network endpoint to write. + /// Thrown when the is not or . + /// + /// Writes a (0 for IPv4, 1 for IPv6), followed by the address bytes and a 2-byte port. + /// public void Put(IPEndPoint endPoint) { if (endPoint.AddressFamily == AddressFamily.InterNetwork) @@ -337,6 +555,14 @@ public void Put(IPEndPoint endPoint) Put((ushort)endPoint.Port); } + /// + /// Serializes a using a 4-byte length header. + /// + /// The to write. + /// + /// Recommended for strings that may exceed the 65535 byte limit of standard length headers.
    + /// Uses . + ///
    public void PutLargeString(string value) { if (string.IsNullOrEmpty(value)) @@ -382,6 +608,88 @@ public void Put(string value, int maxLength = 0) _position += size; } + /// + /// Writes a value of type into the internal byte buffer at the current position, + /// advancing the position by the size of . + /// + /// An unmanaged value type to write into the buffer. + /// The value to write into the buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PutUnmanaged(T value) where T : unmanaged + { + int size = sizeof(T); + if (_autoResize) + { + ResizeIfNeed(_position + size); + } + +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref _data[_position], value); +#else + fixed (byte* ptr = &_data[_position]) + { + *(T*)ptr = value; + } +#endif + + _position += size; + } + + /// + /// Writes a nullable value of type into the internal byte buffer at the current position, + /// first writing a indicating whether the value is present, + /// and then writing the value itself if it exists.
    Advances the position by 1 byte for the presence flag plus + /// the size of if the value is present. + ///
    + /// An unmanaged value type to write into the buffer. + /// The nullable value to write into the buffer. If , only a flag is written. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void PutNullableUnmanaged(T? value) where T : unmanaged + { + bool hasValue = value.HasValue; + Put(hasValue); + if (!hasValue) + { + return; + } + + PutUnmanaged(value.Value); + } + + /// + /// Writes an enum value of type to the internal data buffer at the current position.
    + /// Automatically resizes the buffer if is enabled. + /// Advances the position by the size of . + ///
    + /// An unmanaged enum type to write. + /// The enum value to write. + public void PutEnum(T value) where T : unmanaged, Enum + { + var size = sizeof(T); + if (_autoResize) + { + ResizeIfNeed(_position + size); + } + +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref _data[_position], value); +#else + fixed (byte* ptr = &_data[_position]) + { + *(T*)ptr = value; + } +#endif + _position += size; + } + + /// + /// Serializes an object implementing . + /// + /// A type that implements the interface. + /// The object instance to serialize. + /// + /// This method calls the method on the provided . + /// public void Put(T obj) where T : INetSerializable => obj.Serialize(this); } } From 966da96573bd152bb85181c17f74e7cb6fbc6284 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:37:46 +0100 Subject: [PATCH 116/200] Update NetSerializerTest - Added new Get/PutUnmanaged() methods - Added new GetEnum() method --- LiteNetLib.Tests/NetSerializerTest.cs | 43 +++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/LiteNetLib.Tests/NetSerializerTest.cs b/LiteNetLib.Tests/NetSerializerTest.cs index 301d5d6a..a8bd036a 100644 --- a/LiteNetLib.Tests/NetSerializerTest.cs +++ b/LiteNetLib.Tests/NetSerializerTest.cs @@ -23,15 +23,18 @@ public void Init() SomeGuid = Guid.NewGuid(), SomeVector2 = new SomeVector2(4, 5), SomeVectors = new[] { new SomeVector2(1, 2), new SomeVector2(3, 4) }, + SomeFastVector3 = new SomeFastVector3(0.21f, 100.25f, -400.0f), + SomeFastVectors = new[] { new SomeFastVector3(1.0f, 2.0f, 3.0f), new SomeFastVector3(4.0f, 5.0f, 6.0f) }, SomeEnum = TestEnum.B, SomeByteArray = new byte[] { 255, 1, 0 }, TestObj = new SampleNetSerializable { Value = 5 }, TestArray = new[] { new SampleNetSerializable { Value = 6 }, new SampleNetSerializable { Value = 15 } }, SampleClassArray = new[] - { FillTestArray(new SampleClass { Value = 6 }), FillTestArray(new SampleClass { Value = 15 }) }, + { FillTestArray(new SampleClass { Value = 6, TestEnum = TestEnum.C }), FillTestArray(new SampleClass { Value = 15, TestEnum = TestEnum.B }) }, SampleClassList = new List { FillTestArray(new SampleClass { Value = 1 }), FillTestArray(new SampleClass { Value = 5 }) }, VectorList = new List { new SomeVector2(-1, -2), new SomeVector2(700, 800) }, + FastVectorList = new List { new SomeFastVector3(-100.0f, -200.0f, -300.0f), new SomeFastVector3(100.0f, 200.0f, 300.0f) }, IgnoreMe = 1337 }; @@ -39,6 +42,7 @@ public void Init() _packetProcessor.RegisterNestedType(); _packetProcessor.RegisterNestedType(() => new SampleClass()); _packetProcessor.RegisterNestedType(SomeVector2.Serialize, SomeVector2.Deserialize); + _packetProcessor.RegisterNestedType(SomeFastVector3.Serialize, SomeFastVector3.Deserialize); } private SamplePacket _samplePacket; @@ -70,6 +74,30 @@ public static SomeVector2 Deserialize(NetDataReader reader) } } + private readonly struct SomeFastVector3 + { + public readonly float X; + public readonly float Y; + public readonly float Z; + + public SomeFastVector3(float x, float y, float z) + { + X = x; + Y = y; + Z = z; + } + + public static void Serialize(NetDataWriter writer, SomeFastVector3 vector) + { + writer.PutUnmanaged(vector); + } + + public static SomeFastVector3 Deserialize(NetDataReader reader) + { + return reader.GetUnmanaged(); + } + } + private struct SampleNetSerializable : INetSerializable { public int Value; @@ -89,24 +117,27 @@ private class SampleClass : INetSerializable { public int Value; public ChildClass[] TestArray = Array.Empty(); + public TestEnum TestEnum; public void Serialize(NetDataWriter writer) { writer.Put(Value); writer.PutArray(TestArray); + writer.PutEnum(TestEnum); } public void Deserialize(NetDataReader reader) { Value = reader.GetInt(); TestArray = reader.GetArray(); + TestEnum = reader.GetEnum(); } public override bool Equals(object obj) { var other = (SampleClass)obj; return other.Value == Value && (TestArray is null && other.TestArray is null || TestArray != null && - other.TestArray != null && TestArray.SequenceEqual(other.TestArray)); + other.TestArray != null && TestArray.SequenceEqual(other.TestArray)) && other.TestEnum == TestEnum; } public override int GetHashCode() @@ -157,12 +188,15 @@ private class SamplePacket public Guid SomeGuid { get; set; } public SomeVector2 SomeVector2 { get; set; } public SomeVector2[] SomeVectors { get; set; } + public SomeFastVector3 SomeFastVector3 { get; set; } + public SomeFastVector3[] SomeFastVectors { get; set; } public TestEnum SomeEnum { get; set; } public SampleNetSerializable TestObj { get; set; } public SampleNetSerializable[] TestArray { get; set; } public SampleClass[] SampleClassArray { get; set; } public List SampleClassList { get; set; } public List VectorList { get; set; } + public List FastVectorList { get; set; } [IgnoreDataMember] public int IgnoreMe { get; set; } } @@ -210,6 +244,8 @@ public void CustomPackageTest() Assert.That(readPackage.SomeGuid, Is.EqualTo(_samplePacket.SomeGuid)); Assert.That(readPackage.SomeVector2, Is.EqualTo(_samplePacket.SomeVector2)); Assert.That(readPackage.SomeVectors, Is.EqualTo(_samplePacket.SomeVectors).AsCollection); + Assert.That(readPackage.SomeFastVector3, Is.EqualTo(_samplePacket.SomeFastVector3)); + Assert.That(readPackage.SomeFastVectors, Is.EqualTo(_samplePacket.SomeFastVectors).AsCollection); Assert.That(readPackage.SomeEnum, Is.EqualTo(_samplePacket.SomeEnum)); Assert.That(readPackage.TestObj.Value, Is.EqualTo(_samplePacket.TestObj.Value)); Assert.That(readPackage.TestArray, Is.EqualTo(_samplePacket.TestArray).AsCollection); @@ -218,11 +254,13 @@ public void CustomPackageTest() Assert.That(readPackage.IgnoreMe, Is.EqualTo(0)); // expect 0 because it should be ignored Assert.That(readPackage.SampleClassList, Is.EqualTo(_samplePacket.SampleClassList).AsCollection); Assert.That(readPackage.VectorList, Is.EqualTo(_samplePacket.VectorList).AsCollection); + Assert.That(readPackage.FastVectorList, Is.EqualTo(_samplePacket.FastVectorList).AsCollection); //remove test _samplePacket.SampleClassList.RemoveAt(0); _samplePacket.SampleClassArray = new []{new SampleClass {Value = 1}}; _samplePacket.VectorList.RemoveAt(0); + _samplePacket.FastVectorList.RemoveAt(0); writer.Reset(); _packetProcessor.Write(writer, _samplePacket); @@ -237,6 +275,7 @@ public void CustomPackageTest() _samplePacket.SampleClassList.Add(new SampleClass { Value = 154 }); _samplePacket.SampleClassArray = new[] { new SampleClass { Value = 1 }, new SampleClass { Value = 2 }, new SampleClass { Value = 3 } }; _samplePacket.VectorList.Add(new SomeVector2(500,600)); + _samplePacket.FastVectorList.Add(new SomeFastVector3(500.0f, 600.0f, 700.0f)); writer.Reset(); _packetProcessor.Write(writer, _samplePacket); From d0f2d6efd4715f110844c0cff55d0122e6424c39 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:48:01 +0100 Subject: [PATCH 117/200] Add docs for manualMode --- LiteNetLib/LiteNetManager.Socket.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index b7dd5776..f77c015d 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -325,7 +325,12 @@ private void ReceiveLogic() /// bind to specific ipv4 address /// bind to specific ipv6 address /// port to listen - /// mode of library + /// + /// When , disables internal background threads.
    + /// You must manually call and .

    + /// Recommended for single-threaded environments like Unity or for + /// reducing multi-threading overhead and synchronization issues. + /// public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { if (IsRunning && NotConnected == false) From 352576ba8b041f80136627bba5a9c34876831f7a Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:54:21 +0100 Subject: [PATCH 118/200] Add docs for reject --- LiteNetLib/ConnectionRequest.cs | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 099e08ee..527166a8 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -80,6 +80,16 @@ public LiteNetPeer Accept() return _listener.OnConnectionSolved(this, null, 0, 0); } + /// + /// Rejects the connection request. + /// + /// Optional user data to send along with the rejection packet. + /// Offset in the array. + /// Length of the data to be sent from the array. + /// + /// If , performs a "fire-and-forget" rejection without creating an internal peer. + /// If , creates a temporary peer to ensure the rejection is delivered reliably. + /// public void Reject(byte[] rejectData, int start, int length, bool force) { if (!TryActivate()) @@ -88,27 +98,62 @@ public void Reject(byte[] rejectData, int start, int length, bool force) _listener.OnConnectionSolved(this, rejectData, start, length); } + /// + /// Rejects the connection reliably. Creates a temporary peer to handle packet loss. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void Reject(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, false); + /// + /// Rejects the connection immediately without reliability. + /// Minimizes resource usage by not creating an internal peer. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void RejectForce(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, true); + /// + /// Rejects the connection immediately without reliability and without additional data. + /// public void RejectForce() => Reject(null, 0, 0, true); + /// + /// Rejects the connection immediately without reliability. + /// + /// Data to send with the rejection. public void RejectForce(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, true); + /// + /// Rejects the connection immediately without reliability using data from a . + /// + /// Writer containing the data to send. public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); + /// + /// Rejects the connection reliably without additional data. + /// public void Reject() => Reject(null, 0, 0, false); + /// + /// Rejects the connection reliably. + /// + /// Data to send with the rejection. public void Reject(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, false); + /// + /// Rejects the connection reliably using data from a . + /// + /// Writer containing the data to send. public void Reject(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, false); } From 3f4cd4aa59a2eac37364bfae0941c74859476784 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:54:21 +0100 Subject: [PATCH 119/200] Add docs for reject --- LiteNetLib/ConnectionRequest.cs | 45 +++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 099e08ee..527166a8 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -80,6 +80,16 @@ public LiteNetPeer Accept() return _listener.OnConnectionSolved(this, null, 0, 0); } + /// + /// Rejects the connection request. + /// + /// Optional user data to send along with the rejection packet. + /// Offset in the array. + /// Length of the data to be sent from the array. + /// + /// If , performs a "fire-and-forget" rejection without creating an internal peer. + /// If , creates a temporary peer to ensure the rejection is delivered reliably. + /// public void Reject(byte[] rejectData, int start, int length, bool force) { if (!TryActivate()) @@ -88,27 +98,62 @@ public void Reject(byte[] rejectData, int start, int length, bool force) _listener.OnConnectionSolved(this, rejectData, start, length); } + /// + /// Rejects the connection reliably. Creates a temporary peer to handle packet loss. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void Reject(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, false); + /// + /// Rejects the connection immediately without reliability. + /// Minimizes resource usage by not creating an internal peer. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void RejectForce(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, true); + /// + /// Rejects the connection immediately without reliability and without additional data. + /// public void RejectForce() => Reject(null, 0, 0, true); + /// + /// Rejects the connection immediately without reliability. + /// + /// Data to send with the rejection. public void RejectForce(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, true); + /// + /// Rejects the connection immediately without reliability using data from a . + /// + /// Writer containing the data to send. public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); + /// + /// Rejects the connection reliably without additional data. + /// public void Reject() => Reject(null, 0, 0, false); + /// + /// Rejects the connection reliably. + /// + /// Data to send with the rejection. public void Reject(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, false); + /// + /// Rejects the connection reliably using data from a . + /// + /// Writer containing the data to send. public void Reject(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, false); } From 62d186d8ea921dedcea0c1255c0a9ec374a3014f Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:48:01 +0100 Subject: [PATCH 120/200] Add docs for manualMode --- LiteNetLib/LiteNetManager.Socket.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index b7dd5776..f77c015d 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -325,7 +325,12 @@ private void ReceiveLogic() /// bind to specific ipv4 address /// bind to specific ipv6 address /// port to listen - /// mode of library + /// + /// When , disables internal background threads.
    + /// You must manually call and .

    + /// Recommended for single-threaded environments like Unity or for + /// reducing multi-threading overhead and synchronization issues. + /// public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { if (IsRunning && NotConnected == false) From 64cb08f4ce31f608cffd94e9812f47a9456f9fcd Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:57:22 +0100 Subject: [PATCH 121/200] Revert "Add docs for manualMode" This reverts commit d0f2d6efd4715f110844c0cff55d0122e6424c39. --- LiteNetLib/LiteNetManager.Socket.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index f77c015d..b7dd5776 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -325,12 +325,7 @@ private void ReceiveLogic() /// bind to specific ipv4 address /// bind to specific ipv6 address /// port to listen - /// - /// When , disables internal background threads.
    - /// You must manually call and .

    - /// Recommended for single-threaded environments like Unity or for - /// reducing multi-threading overhead and synchronization issues. - /// + /// mode of library public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { if (IsRunning && NotConnected == false) From 3e758a791d4f9c00ac280f8381ba59d59c9ded74 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:57:28 +0100 Subject: [PATCH 122/200] Revert "Add docs for reject" This reverts commit 352576ba8b041f80136627bba5a9c34876831f7a. --- LiteNetLib/ConnectionRequest.cs | 45 --------------------------------- 1 file changed, 45 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 527166a8..099e08ee 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -80,16 +80,6 @@ public LiteNetPeer Accept() return _listener.OnConnectionSolved(this, null, 0, 0); } - /// - /// Rejects the connection request. - /// - /// Optional user data to send along with the rejection packet. - /// Offset in the array. - /// Length of the data to be sent from the array. - /// - /// If , performs a "fire-and-forget" rejection without creating an internal peer. - /// If , creates a temporary peer to ensure the rejection is delivered reliably. - /// public void Reject(byte[] rejectData, int start, int length, bool force) { if (!TryActivate()) @@ -98,62 +88,27 @@ public void Reject(byte[] rejectData, int start, int length, bool force) _listener.OnConnectionSolved(this, rejectData, start, length); } - /// - /// Rejects the connection reliably. Creates a temporary peer to handle packet loss. - /// - /// Data to send with the rejection. - /// Offset in the array. - /// Length of the data to be sent. public void Reject(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, false); - /// - /// Rejects the connection immediately without reliability. - /// Minimizes resource usage by not creating an internal peer. - /// - /// Data to send with the rejection. - /// Offset in the array. - /// Length of the data to be sent. public void RejectForce(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, true); - /// - /// Rejects the connection immediately without reliability and without additional data. - /// public void RejectForce() => Reject(null, 0, 0, true); - /// - /// Rejects the connection immediately without reliability. - /// - /// Data to send with the rejection. public void RejectForce(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, true); - /// - /// Rejects the connection immediately without reliability using data from a . - /// - /// Writer containing the data to send. public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); - /// - /// Rejects the connection reliably without additional data. - /// public void Reject() => Reject(null, 0, 0, false); - /// - /// Rejects the connection reliably. - /// - /// Data to send with the rejection. public void Reject(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, false); - /// - /// Rejects the connection reliably using data from a . - /// - /// Writer containing the data to send. public void Reject(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, false); } From daece50b4f7e92595dcc0c59dbb43e3fb1f45be1 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 23:06:09 +0100 Subject: [PATCH 123/200] Update disconnect docs --- LiteNetLib/LiteNetManager.cs | 15 +++++++++++++++ LiteNetLib/LiteNetPeer.cs | 11 +++++++++++ 2 files changed, 26 insertions(+) diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 572fd105..dfac720a 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -301,6 +301,21 @@ internal void DisconnectPeerForce(LiteNetPeer peer, NetPacket eventData) => DisconnectPeer(peer, reason, socketErrorCode, true, null, 0, 0, eventData); + /// + /// Disconnects a peer and handles internal state cleanup. + /// + /// The peer to disconnect. + /// The reason for disconnection provided to the event listener. + /// The error code from the underlying socket, if any. + /// + /// If , immediately sets state to Disconnected without sending a notification. + /// If , sends a single unreliable disconnect packet and sets state to ShutdownRequested.
    + /// Queued reliable packets are not guaranteed to be delivered before the state change. + /// + /// Optional custom data to include in the disconnect packet. + /// Offset in the array. + /// Number of bytes to send from the array. + /// Internal packet data associated with the disconnect event. private void DisconnectPeer( LiteNetPeer peer, DisconnectReason reason, diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 7c1d86bb..4109f6bb 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -698,6 +698,17 @@ internal virtual void AddToReliableChannelSendQueue(BaseChannel channel) } + /// + /// Internally handles the shutdown process for this peer. + /// + /// Optional data to include in the disconnect packet. + /// Offset in the array. + /// Length of the data to send. + /// + /// If , immediately sets state to Disconnected without sending a notification. + /// If , sends a single unreliable disconnect packet and sets state to ShutdownRequested. + /// + /// A indicating the state change transition. internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) { lock (_shutdownLock) From 4ca89a7d21cfe8b98633f1a75958078934e37ed9 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 20 Mar 2026 22:54:21 +0100 Subject: [PATCH 124/200] Update docs --- LiteNetLib/ConnectionRequest.cs | 45 +++++++++++++++++++++++++++++ LiteNetLib/LiteNetManager.Socket.cs | 7 ++++- LiteNetLib/LiteNetManager.cs | 28 +++++++++++++++--- LiteNetLib/LiteNetPeer.cs | 21 ++++++++++++++ 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 099e08ee..32b965eb 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -80,6 +80,16 @@ public LiteNetPeer Accept() return _listener.OnConnectionSolved(this, null, 0, 0); } + /// + /// Rejects the connection request. + /// + /// Optional user data to send along with the rejection packet. + /// Offset in the array. + /// Length of the data to be sent from the array. + /// + /// If , sends a single raw packet and immediately removes the request.
    + /// If , creates a temporary peer that sends a single rejection packet and lingers in memory until a timeout occurs to handle late-arriving packets. + /// public void Reject(byte[] rejectData, int start, int length, bool force) { if (!TryActivate()) @@ -88,27 +98,62 @@ public void Reject(byte[] rejectData, int start, int length, bool force) _listener.OnConnectionSolved(this, rejectData, start, length); } + /// + /// Rejects the connection reliably. Creates a temporary peer to handle packet loss. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void Reject(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, false); + /// + /// Rejects the connection immediately without reliability. + /// Minimizes resource usage by not creating an internal peer. + /// + /// Data to send with the rejection. + /// Offset in the array. + /// Length of the data to be sent. public void RejectForce(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, true); + /// + /// Rejects the connection immediately without reliability and without additional data. + /// public void RejectForce() => Reject(null, 0, 0, true); + /// + /// Rejects the connection immediately without reliability. + /// + /// Data to send with the rejection. public void RejectForce(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, true); + /// + /// Rejects the connection immediately without reliability using data from a . + /// + /// Writer containing the data to send. public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); + /// + /// Rejects the connection reliably without additional data. + /// public void Reject() => Reject(null, 0, 0, false); + /// + /// Rejects the connection reliably. + /// + /// Data to send with the rejection. public void Reject(byte[] rejectData) => Reject(rejectData, 0, rejectData.Length, false); + /// + /// Rejects the connection reliably using data from a . + /// + /// Writer containing the data to send. public void Reject(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, false); } diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index b7dd5776..f77c015d 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -325,7 +325,12 @@ private void ReceiveLogic() /// bind to specific ipv4 address /// bind to specific ipv6 address /// port to listen - /// mode of library + /// + /// When , disables internal background threads.
    + /// You must manually call and .

    + /// Recommended for single-threaded environments like Unity or for + /// reducing multi-threading overhead and synchronization issues. + /// public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { if (IsRunning && NotConnected == false) diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 572fd105..e7b0102f 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -301,6 +301,21 @@ internal void DisconnectPeerForce(LiteNetPeer peer, NetPacket eventData) => DisconnectPeer(peer, reason, socketErrorCode, true, null, 0, 0, eventData); + /// + /// Disconnects a peer and handles internal state cleanup. + /// + /// The peer to disconnect. + /// The reason for disconnection provided to the event listener. + /// The error code from the underlying socket, if any. + /// + /// If , immediately sets state to without sending a notification.
    + /// If , sends a single unreliable disconnect packet and sets state to . + /// Peer will linger until to ignore late-arriving packets from the old session. + /// + /// Optional custom data to include in the disconnect packet. + /// Offset in the array. + /// Number of bytes to send from the array. + /// Internal packet data associated with the disconnect event. private void DisconnectPeer( LiteNetPeer peer, DisconnectReason reason, @@ -562,9 +577,12 @@ private void ProcessDelayedPackets() /// - /// Update and send logic. Use this only when NetManager started in manual mode + /// Updates internal peer states, handles timeouts, and processes NTP requests. /// - /// elapsed milliseconds since last update call + /// Time passed since the last update frame. + /// + /// Must be called continuously from the main loop if was set to . + /// public void ManualUpdate(float elapsedMilliseconds) { if (!_manualMode) @@ -1278,9 +1296,11 @@ public void TriggerUpdate() => _updateTriggerEvent.Set(); /// - /// Receive" pending events. Call this in game update code - /// In Manual mode it will call also socket Receive (which can be slow) + /// Reads data from the UDP sockets and processes pending events immediately. /// + /// + /// Must be called continuously from the main loop if was set to . + /// public void PollEvents() { if (_manualMode) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 7c1d86bb..dacce2c6 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -698,6 +698,18 @@ internal virtual void AddToReliableChannelSendQueue(BaseChannel channel) } + /// + /// Internally handles the shutdown process for this peer. + /// + /// Optional data to include in the unreliable disconnect packet. + /// Offset in the array. + /// Length of the data to send. + /// + /// If , immediately sets state to without sending a notification.
    + /// If , sends a single unreliable disconnect packet and sets state to + /// Queued reliable packets are bypassed and dropped immediately. + /// + /// A indicating the state change transition. internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) { lock (_shutdownLock) @@ -929,6 +941,15 @@ private void UpdateMtuLogic(float deltaTime) } } + /// + /// Evaluates incoming connection requests against the current peer state to supply Reconnect Protection. + /// + /// The incoming connection request packet. + /// A directing how the manager should handle the request. + /// + /// If the state is , the peer lingers to ignore older connection requests + /// (where the packet timestamp is smaller than internal ), ensuring delayed or stale packets are dropped. + /// internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket connRequest) { //current or new request From 9d5d42f11ea8361a0212891cca23c14a24718252 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sat, 21 Mar 2026 00:04:04 +0100 Subject: [PATCH 125/200] Refine docs --- LiteNetLib/Utils/NetDataReader.cs | 242 +++++++++++++++--------------- LiteNetLib/Utils/NetDataWriter.cs | 81 +++++----- 2 files changed, 166 insertions(+), 157 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 3271c064..30597f01 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -14,7 +14,7 @@ public unsafe class NetDataReader protected int _offset; /// - /// Gets the internal array containing the raw network data. + /// Gets the internal array containing the raw network data. /// public byte[] RawData { @@ -77,7 +77,7 @@ public bool EndOfData } /// - /// Gets the number of s remaining to be read. + /// Gets the number of s remaining to be read. /// public int AvailableBytes { @@ -86,9 +86,9 @@ public int AvailableBytes } /// - /// Verifies that the buffer has at least s available to read. + /// Verifies that the buffer has at least s available to read. /// - /// The number of s required. + /// The number of s required. /// Thrown if exceeds or is negative. [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EnsureAvailable(int count) @@ -101,7 +101,7 @@ private void EnsureAvailable(int count) /// /// Advances the by the specified . /// - /// The number of s to skip. + /// The number of s to skip. public void SkipBytes(int count) => _position += count; /// @@ -123,9 +123,9 @@ public void SetSource(NetDataWriter dataWriter) } /// - /// Reinitializes the reader using a array. + /// Reinitializes the reader using a array. /// - /// The source array. + /// The source array. public void SetSource(byte[] source) { _data = source; @@ -135,11 +135,11 @@ public void SetSource(byte[] source) } /// - /// Reinitializes the reader using a segment of a array. + /// Reinitializes the reader using a segment of a array. /// - /// The source array. + /// The source array. /// The starting index for reading. - /// The total number of s available to read from the . + /// The total number of s available to read from the . public void SetSource(byte[] source, int offset, int maxSize) { _data = source; @@ -192,8 +192,8 @@ public void Get(out T result, Func constructor) where T : class, INetSeria /// /// The deserialized . /// - /// Reads a to determine the (0 for IPv4, 1 for IPv6), - /// followed by the address bytes and a 2-byte port. + /// Reads a to determine the (0 for IPv4, 1 for IPv6), + /// followed by the address bytes and a 2-byte port. /// public IPEndPoint GetIPEndPoint() { @@ -215,59 +215,59 @@ public IPEndPoint GetIPEndPoint() return new IPEndPoint(address, GetUShort()); } - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out byte result) => result = GetByte(); - /// Reads an and assigns it to . + /// Reads an and assigns it to . public void Get(out sbyte result) => result = (sbyte)GetByte(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out bool result) => result = GetBool(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out char result) => result = GetChar(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out ushort result) => result = GetUShort(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out short result) => result = GetShort(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out ulong result) => result = GetULong(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out long result) => result = GetLong(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out uint result) => result = GetUInt(); - /// Reads an and assigns it to . + /// Reads an and assigns it to . public void Get(out int result) => result = GetInt(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out double result) => result = GetDouble(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out float result) => result = GetFloat(); - /// Reads a and assigns it to . + /// Reads a and assigns it to . public void Get(out string result) => result = GetString(); - /// Reads a with a length limit and assigns it to . + /// Reads a with a length limit and assigns it to . public void Get(out string result, int maxLength) => result = GetString(maxLength); /// Reads a and assigns it to . public void Get(out Guid result) => result = GetGuid(); - /// Reads the next from the buffer. + /// Reads the next from the buffer. public byte GetByte() => _data[_position++]; - /// Reads the next from the buffer. + /// Reads the next from the buffer. public sbyte GetSByte() => (sbyte)GetByte(); /// - /// Reads an array of unmanaged values prefixed by a length. + /// Reads an array of unmanaged values prefixed by a length. /// /// An unmanaged type. /// A new array of type . @@ -286,7 +286,7 @@ public T[] GetUnmanagedArray() where T : unmanaged /// Reads an array of values by performing a direct memory copy. /// /// The element type. - /// The size of a single element in s. + /// The size of a single element in s. /// A new array of type . public T[] GetArray(ushort size) { @@ -336,39 +336,39 @@ public T[] GetArray(Func constructor) where T : class, INetSerializable return result; } - /// Reads an array of values. + /// Reads an array of values. public bool[] GetBoolArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public ushort[] GetUShortArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public short[] GetShortArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public int[] GetIntArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public uint[] GetUIntArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public float[] GetFloatArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public double[] GetDoubleArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public long[] GetLongArray() => GetUnmanagedArray(); - /// Reads an array of values. + /// Reads an array of values. public ulong[] GetULongArray() => GetUnmanagedArray(); /// - /// Reads an array of values. + /// Reads an array of values. /// - /// A new array. + /// A new array. /// - /// Reads a 2-byte length header followed by each element. + /// Reads a 2-byte length header followed by each element. /// public string[] GetStringArray() { @@ -382,10 +382,10 @@ public string[] GetStringArray() } /// - /// Reads an array of values with a maximum character limit per element. + /// Reads an array of values with a maximum character limit per element. /// - /// The maximum number of characters allowed per . - /// A new array. + /// The maximum number of characters allowed per . + /// A new array. /// /// Strings exceeding are returned as . /// @@ -400,44 +400,44 @@ public string[] GetStringArray(int maxStringLength) return arr; } - /// Reads a value from the current position. + /// Reads a value from the current position. /// if the byte is 1; otherwise, . public bool GetBool() => GetByte() == 1; - /// Reads a value as a 2-byte . + /// Reads a value as a 2-byte . public char GetChar() => (char)GetUShort(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public ushort GetUShort() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public short GetShort() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public long GetLong() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public ulong GetULong() => GetUnmanaged(); - /// Reads an value using unmanaged memory access. + /// Reads an value using unmanaged memory access. public int GetInt() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public uint GetUInt() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public float GetFloat() => GetUnmanaged(); - /// Reads a value using unmanaged memory access. + /// Reads a value using unmanaged memory access. public double GetDouble() => GetUnmanaged(); /// - /// Reads a with a maximum character limit. + /// Reads a with a maximum character limit. /// /// The maximum allowed character count. - /// The deserialized , or if the character count exceeds . + /// The deserialized , or if the character count exceeds . /// - /// Note that limits the number of characters, not the total size in s. + /// Note that limits the number of characters, not the total size in s. /// public string GetString(int maxLength) { @@ -458,9 +458,9 @@ public string GetString(int maxLength) } /// - /// Reads a from the current position. + /// Reads a from the current position. /// - /// The deserialized . + /// The deserialized . public string GetString() { ushort size = GetUShort(); @@ -476,9 +476,9 @@ public string GetString() } /// - /// Reads a prefixed with a 4-byte length header. + /// Reads a prefixed with a 4-byte length header. /// - /// The deserialized . + /// The deserialized . public string GetLargeString() { int size = GetInt(); @@ -505,9 +505,9 @@ public Guid GetGuid() } /// - /// Gets an of s from the current position. + /// Gets an of s from the current position. /// - /// The number of s to include in the segment. + /// The number of s to include in the segment. /// An wrapping the internal buffer. public ArraySegment GetBytesSegment(int count) { @@ -518,7 +518,7 @@ public ArraySegment GetBytesSegment(int count) } /// - /// Gets an containing all remaining s. + /// Gets an containing all remaining s. /// /// An from the current position to the end of the data. public ArraySegment GetRemainingBytesSegment() @@ -554,7 +554,7 @@ public T Get(Func constructor) where T : class, INetSerializable } /// - /// Returns a of s containing all remaining data. + /// Returns a of s containing all remaining data. /// /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -562,7 +562,7 @@ public ReadOnlySpan GetRemainingBytesSpan() => new ReadOnlySpan(_data, _position, _dataSize - _position); /// - /// Returns a of s containing all remaining data. + /// Returns a of s containing all remaining data. /// /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -570,9 +570,9 @@ public ReadOnlyMemory GetRemainingBytesMemory() => new ReadOnlyMemory(_data, _position, _dataSize - _position); /// - /// Reads all remaining s and returns them as a new array. + /// Reads all remaining s and returns them as a new array. /// - /// A new array containing the remaining data. + /// A new array containing the remaining data. /// /// This method performs a heap allocation and advances the to the end of the data. /// @@ -585,11 +585,11 @@ public byte[] GetRemainingBytes() } /// - /// Copies a specified number of s into a destination array at a specific offset. + /// Copies a specified number of s into a destination array at a specific offset. /// /// The array to copy data into. /// The starting index in the array. - /// The number of s to read. + /// The number of s to read. public void GetBytes(byte[] destination, int start, int count) { EnsureAvailable(count); @@ -598,10 +598,10 @@ public void GetBytes(byte[] destination, int start, int count) } /// - /// Copies a specified number of s into a destination array starting at index 0. + /// Copies a specified number of s into a destination array starting at index 0. /// /// The array to copy data into. - /// The number of s to read. + /// The number of s to read. public void GetBytes(byte[] destination, int count) { EnsureAvailable(count); @@ -610,15 +610,15 @@ public void GetBytes(byte[] destination, int count) } /// - /// Reads an array prefixed with its length. + /// Reads an array prefixed with its length. /// - /// A new array. + /// A new array. public sbyte[] GetSBytesWithLength() => GetUnmanagedArray(); /// - /// Reads a array prefixed with its length. + /// Reads a array prefixed with its length. /// - /// A new array. + /// A new array. public byte[] GetBytesWithLength() => GetUnmanagedArray(); /// @@ -702,44 +702,44 @@ public ReadOnlySpan GetSpan(int length) #region PeekMethods - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public byte PeekByte() => _data[_position]; - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public sbyte PeekSByte() => (sbyte)_data[_position]; - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public bool PeekBool() => _data[_position] == 1; - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public char PeekChar() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public ushort PeekUShort() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public short PeekShort() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public long PeekLong() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public ulong PeekULong() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public int PeekInt() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public uint PeekUInt() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public float PeekFloat() => PeekUnmanaged(); - /// Reads the at the current position without advancing the . + /// Reads the at the current position without advancing the . public double PeekDouble() => PeekUnmanaged(); /// - /// Reads a with a character limit without advancing the . + /// Reads a with a character limit without advancing the . /// /// Maximum allowed character count. /// Strings exceeding are returned as . @@ -756,7 +756,7 @@ public string PeekString(int maxLength) } /// - /// Reads a without advancing the . + /// Reads a without advancing the . /// public string PeekString() { @@ -790,8 +790,8 @@ public T PeekUnmanaged() where T : unmanaged #endregion #region TryGetMethods - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetByte(out byte result) { @@ -804,8 +804,8 @@ public bool TryGetByte(out byte result) return false; } - /// Attempts to read an without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read an without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetSByte(out sbyte result) { @@ -818,8 +818,8 @@ public bool TryGetSByte(out sbyte result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or if failed. /// if enough data was available; otherwise, . public bool TryGetBool(out bool result) { @@ -832,8 +832,8 @@ public bool TryGetBool(out bool result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or '\0' if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or '\0' if failed. /// if enough data was available; otherwise, . public bool TryGetChar(out char result) { @@ -846,8 +846,8 @@ public bool TryGetChar(out char result) return true; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetShort(out short result) { @@ -860,8 +860,8 @@ public bool TryGetShort(out short result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetUShort(out ushort result) { @@ -874,8 +874,8 @@ public bool TryGetUShort(out ushort result) return false; } - /// Attempts to read an without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read an without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetInt(out int result) { @@ -888,8 +888,8 @@ public bool TryGetInt(out int result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetUInt(out uint result) { @@ -902,8 +902,8 @@ public bool TryGetUInt(out uint result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetLong(out long result) { @@ -916,8 +916,8 @@ public bool TryGetLong(out long result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetULong(out ulong result) { @@ -930,8 +930,8 @@ public bool TryGetULong(out ulong result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetFloat(out float result) { @@ -944,8 +944,8 @@ public bool TryGetFloat(out float result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or 0 if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . public bool TryGetDouble(out double result) { @@ -958,8 +958,8 @@ public bool TryGetDouble(out double result) return false; } - /// Attempts to read a without throwing an exception. - /// The deserialized , or if failed. + /// Attempts to read a without throwing an exception. + /// The deserialized , or if failed. /// if enough data was available; otherwise, . public bool TryGetString(out string result) { @@ -978,8 +978,8 @@ public bool TryGetString(out string result) return false; } - /// Attempts to read a array without throwing an exception. - /// The deserialized array, or if failed. + /// Attempts to read a array without throwing an exception. + /// The deserialized array, or if failed. /// if enough data was available; otherwise, . public bool TryGetStringArray(out string[] result) { @@ -1002,8 +1002,8 @@ public bool TryGetStringArray(out string[] result) return true; } - /// Attempts to read a array with a length header without throwing an exception. - /// The deserialized array, or if failed. + /// Attempts to read a array with a length header without throwing an exception. + /// The deserialized array, or if failed. /// if enough data was available; otherwise, . public bool TryGetBytesWithLength(out byte[] result) { diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 0849c0a3..9420c969 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -15,7 +15,7 @@ public unsafe class NetDataWriter private readonly bool _autoResize; /// - /// Gets the total capacity of the internal buffer. + /// Gets the total capacity of the internal buffer. /// /// The length of the underlying array. public int Capacity @@ -25,7 +25,7 @@ public int Capacity } /// - /// Gets the underlying array used by this writer. + /// Gets the underlying array used by this writer. /// /// The internal array. /// @@ -38,7 +38,7 @@ public byte[] Data } /// - /// Gets the current number of s written to the buffer. + /// Gets the current number of s written to the buffer. /// /// The current . public int Length @@ -109,10 +109,10 @@ public static NetDataWriter FromBytes(Span bytes) } /// - /// Creates a new and serializes a into it. + /// Creates a new and serializes a into it. /// - /// The to serialize. - /// A new instance containing the serialized . + /// The to serialize. + /// A new instance containing the serialized . public static NetDataWriter FromString(string value) { var netDataWriter = new NetDataWriter(); @@ -138,9 +138,9 @@ public void ResizeIfNeed(int newSize) } /// - /// Ensures the internal buffer can accommodate more s. + /// Ensures the internal buffer can accommodate more s. /// - /// The number of additional s to fit. + /// The number of additional s to fit. /// /// This checks against the current . If the capacity is insufficient, /// the buffer grows to either the required size or doubles its current size. @@ -160,7 +160,7 @@ public void EnsureFit(int additionalSize) /// /// The minimum capacity required for the internal buffer. /// - /// If the current buffer is smaller than , will allocate a larger array. + /// If the current buffer is smaller than , will allocate a larger array. /// public void Reset(int size) { @@ -174,9 +174,9 @@ public void Reset(int size) public void Reset() => _position = 0; /// - /// Creates a array containing the current data from the internal buffer. + /// Creates a array containing the current data from the internal buffer. /// - /// A new array of length . + /// A new array of length . /// /// This method performs a heap allocation and copies the data using . /// @@ -278,18 +278,18 @@ public void Put(Guid value) } /// - /// Serializes a segment of a array. + /// Serializes a segment of a array. /// /// The source array. /// The starting index in the source array. - /// The number of s to write. + /// The number of s to write. public void Put(byte[] data, int offset, int length) { Put(data.AsSpan(offset, length)); } /// - /// Serializes an entire array. + /// Serializes an entire array. /// /// The source array. public void Put(byte[] data) @@ -310,9 +310,9 @@ public void Put(ReadOnlySpan data) } /// - /// Serializes a segment of an array prefixed with its length. + /// Serializes a segment of an array prefixed with its length. /// - /// The source array. + /// The source array. /// The starting index in the source array. /// The number of elements to write. public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) @@ -343,17 +343,17 @@ public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) } /// - /// Serializes an array prefixed with its length. + /// Serializes an array prefixed with its length. /// /// The source array. public void PutSBytesWithLength(sbyte[] data) => PutArray(data, 1); /// - /// Serializes a segment of a array prefixed with its length. + /// Serializes a segment of a array prefixed with its length. /// - /// The source array. + /// The source array. /// The starting index in the source array. - /// The number of s to write. + /// The number of s to write. public void PutBytesWithLength(byte[] data, int offset, ushort length) { if (_autoResize) @@ -379,22 +379,22 @@ public void PutBytesWithLength(byte[] data, int offset, ushort length) } /// - /// Serializes a array prefixed with its length. + /// Serializes a array prefixed with its length. /// /// The source array. public void PutBytesWithLength(byte[] data) => PutArray(data, 1); /// - /// Serializes a value as a single . + /// Serializes a value as a single . /// - /// The value to write. + /// The value to write. public void Put(bool value) => Put((byte)(value ? 1 : 0)); /// - /// Serializes an prefixed with a 2-byte length. + /// Serializes an prefixed with a 2-byte length. /// /// The source array to serialize. - /// The size of a single element in s. + /// The size of a single element in s. /// /// If the array is , a length of 0 is written.
    /// The total payload size is calculated as length * sz. @@ -488,11 +488,11 @@ public void PutSpan(Span span) where T : unmanaged public void PutArray(bool[] value) => PutUnmanagedArray(value); /// - /// Serializes an array of values. + /// Serializes an array of values. /// - /// The array of elements to write. + /// The array of elements to write. /// - /// Writes a 2-byte length header followed by each element. + /// Writes a 2-byte length header followed by each element. /// public void PutArray(string[] value) { @@ -503,10 +503,10 @@ public void PutArray(string[] value) } /// - /// Serializes an array of values with a maximum length constraint per element. + /// Serializes an array of values with a maximum length constraint per element. /// - /// The array of elements to write. - /// The maximum allowed length for each individual . + /// The array of elements to write. + /// The maximum allowed length for each individual . public void PutArray(string[] value, int strMaxLength) { ushort strArrayLength = value == null ? (ushort)0 : (ushort)value.Length; @@ -534,7 +534,7 @@ public void PutArray(string[] value, int strMaxLength) /// The network endpoint to write. /// Thrown when the is not or . /// - /// Writes a (0 for IPv4, 1 for IPv6), followed by the address bytes and a 2-byte port. + /// Writes a (0 for IPv4, 1 for IPv6), followed by the address bytes and a 2-byte port. /// public void Put(IPEndPoint endPoint) { @@ -556,11 +556,11 @@ public void Put(IPEndPoint endPoint) } /// - /// Serializes a using a 4-byte length header. + /// Serializes a using a 4-byte length header. /// - /// The to write. + /// The to write. /// - /// Recommended for strings that may exceed the 65535 byte limit of standard length headers.
    + /// Recommended for strings that may exceed the 65535 byte limit of standard length headers.
    /// Uses . ///
    public void PutLargeString(string value) @@ -584,8 +584,17 @@ public void PutLargeString(string value) } /// - /// Note that "maxLength" only limits the number of characters in a string, not its size in bytes. + /// Serializes a string using a 2-byte length header. /// + /// The string to write to the buffer. + /// + /// The maximum number of characters to write. If the string is longer, it will be truncated.
    + /// A value of 0 indicates no limit. + /// + /// + /// Note that limits the number of characters, not the total size in s.
    + /// Uses . + ///
    public void Put(string value, int maxLength = 0) { if (string.IsNullOrEmpty(value)) From ad6b8f613b6bb6872756ab7f3e1d38ed5e0e85da Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sat, 21 Mar 2026 00:31:22 +0100 Subject: [PATCH 126/200] Use FastBitConverter --- LiteNetLib/Utils/NetDataWriter.cs | 47 ++++--------------------------- 1 file changed, 5 insertions(+), 42 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 9420c969..197fc717 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -322,14 +322,7 @@ public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) ResizeIfNeed(_position + 2 + length); } -#if NET8_0_OR_GREATER - Unsafe.WriteUnaligned(ref _data[_position], length); -#else - fixed (byte* ptr = &_data[_position]) - { - *(ushort*)ptr = length; - } -#endif + FastBitConverter.GetBytes(_data, _position, length); _position += 2; if (length > 0) @@ -361,14 +354,7 @@ public void PutBytesWithLength(byte[] data, int offset, ushort length) ResizeIfNeed(_position + 2 + length); } -#if NET8_0_OR_GREATER - Unsafe.WriteUnaligned(ref _data[_position], length); -#else - fixed (byte* ptr = &_data[_position]) - { - *(ushort*)ptr = length; - } -#endif + FastBitConverter.GetBytes(_data, _position, length); _position += 2; if (length > 0) @@ -440,14 +426,7 @@ public void PutSpan(Span span) where T : unmanaged ResizeIfNeed(_position + byteLength + 2); } -#if NET8_0_OR_GREATER - Unsafe.WriteUnaligned(ref _data[_position], length); -#else - fixed (byte* ptr = &_data[_position]) - { - *(ushort*)ptr = length; - } -#endif + FastBitConverter.GetBytes(_data, _position, length); _position += 2; if (length > 0) @@ -631,16 +610,7 @@ public void PutUnmanaged(T value) where T : unmanaged { ResizeIfNeed(_position + size); } - -#if NET8_0_OR_GREATER - Unsafe.WriteUnaligned(ref _data[_position], value); -#else - fixed (byte* ptr = &_data[_position]) - { - *(T*)ptr = value; - } -#endif - + FastBitConverter.GetBytes(_data, _position, value); _position += size; } @@ -680,14 +650,7 @@ public void PutEnum(T value) where T : unmanaged, Enum ResizeIfNeed(_position + size); } -#if NET8_0_OR_GREATER - Unsafe.WriteUnaligned(ref _data[_position], value); -#else - fixed (byte* ptr = &_data[_position]) - { - *(T*)ptr = value; - } -#endif + FastBitConverter.GetBytes(_data, _position, value); _position += size; } From fc24c7ca51829bf4ec792cc6a6937ced7f1aa03d Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sat, 21 Mar 2026 00:33:53 +0100 Subject: [PATCH 127/200] Formatting --- LiteNetLib/Utils/NetDataWriter.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 197fc717..08320a28 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -318,9 +318,7 @@ public void Put(ReadOnlySpan data) public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) { if (_autoResize) - { ResizeIfNeed(_position + 2 + length); - } FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -350,9 +348,7 @@ public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) public void PutBytesWithLength(byte[] data, int offset, ushort length) { if (_autoResize) - { ResizeIfNeed(_position + 2 + length); - } FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -422,9 +418,7 @@ public void PutSpan(Span span) where T : unmanaged var byteLength = length * sizeof(T); if (_autoResize) - { ResizeIfNeed(_position + byteLength + 2); - } FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -607,9 +601,7 @@ public void PutUnmanaged(T value) where T : unmanaged { int size = sizeof(T); if (_autoResize) - { ResizeIfNeed(_position + size); - } FastBitConverter.GetBytes(_data, _position, value); _position += size; } From 99a909f28a35f9eaa93ae18fdf9c787db8082c31 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sat, 21 Mar 2026 00:48:57 +0100 Subject: [PATCH 128/200] Use WriteUnaligned --- LiteNetLib/Utils/FastBitConverter.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/FastBitConverter.cs b/LiteNetLib/Utils/FastBitConverter.cs index 82bedf4e..b067a3db 100644 --- a/LiteNetLib/Utils/FastBitConverter.cs +++ b/LiteNetLib/Utils/FastBitConverter.cs @@ -14,7 +14,9 @@ public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) whe int size = sizeof(T); if (bytes.Length < startIndex + size) ThrowIndexOutOfRangeException(); -#if NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER +#if NET8_0_OR_GREATER + Unsafe.WriteUnaligned(ref bytes[startIndex], value); +#elif NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER Unsafe.As(ref bytes[startIndex]) = value; #else fixed (byte* ptr = &bytes[startIndex]) From 8d2854e4b5c187c6acf4c57224315debc0af0260 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sat, 21 Mar 2026 01:03:53 +0100 Subject: [PATCH 129/200] Update GetEnum --- LiteNetLib/Utils/NetDataReader.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 30597f01..7d109031 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -680,7 +680,9 @@ public T GetUnmanaged() where T : unmanaged /// The enum value read from the buffer. public T GetEnum() where T : unmanaged, Enum { - var span = GetSpan(sizeof(T)); + int size = sizeof(T); + ReadOnlySpan span = new ReadOnlySpan(_data, _position, size); + _position += size; #if NET8_0_OR_GREATER return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(span)); #else @@ -691,13 +693,6 @@ public T GetEnum() where T : unmanaged, Enum #endif } - public ReadOnlySpan GetSpan(int length) - { - ReadOnlySpan span = new ReadOnlySpan(_data, _position, length); - _position += length; - return span; - } - #endregion #region PeekMethods From 0032ef126dfef345942c856a09922537ccbef1c2 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Sun, 22 Mar 2026 12:54:33 +0200 Subject: [PATCH 130/200] little tunes --- LiteNetLib/Utils/NetDataReader.cs | 8 ++++---- LiteNetLib/Utils/NetDataWriter.cs | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 7d109031..fcf3ee04 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -6,7 +6,7 @@ namespace LiteNetLib.Utils { - public unsafe class NetDataReader + public class NetDataReader { protected byte[] _data; protected int _position; @@ -271,7 +271,7 @@ public IPEndPoint GetIPEndPoint() /// /// An unmanaged type. /// A new array of type . - public T[] GetUnmanagedArray() where T : unmanaged + public unsafe T[] GetUnmanagedArray() where T : unmanaged { ushort length = GetUShort(); int byteLength = length * sizeof(T); @@ -629,7 +629,7 @@ public void GetBytes(byte[] destination, int count) /// The value of type read from the buffer. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T GetUnmanaged() where T : unmanaged + public unsafe T GetUnmanaged() where T : unmanaged { var size = sizeof(T); EnsureAvailable(size); @@ -678,7 +678,7 @@ public T GetUnmanaged() where T : unmanaged /// /// An unmanaged enum type to read. /// The enum value read from the buffer. - public T GetEnum() where T : unmanaged, Enum + public unsafe T GetEnum() where T : unmanaged, Enum { int size = sizeof(T); ReadOnlySpan span = new ReadOnlySpan(_data, _position, size); diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 08320a28..5c00a6e4 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -7,7 +7,7 @@ namespace LiteNetLib.Utils { - public unsafe class NetDataWriter + public class NetDataWriter { protected byte[] _data; protected int _position; @@ -412,7 +412,7 @@ public void PutUnmanagedArray(T[] arr) where T : unmanaged /// Writes a 2-byte length header followed by the raw binary data.
    ///
    [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PutSpan(Span span) where T : unmanaged + public unsafe void PutSpan(Span span) where T : unmanaged { var length = (ushort)span.Length; var byteLength = length * sizeof(T); @@ -597,7 +597,7 @@ public void Put(string value, int maxLength = 0) /// An unmanaged value type to write into the buffer. /// The value to write into the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void PutUnmanaged(T value) where T : unmanaged + public unsafe void PutUnmanaged(T value) where T : unmanaged { int size = sizeof(T); if (_autoResize) @@ -608,7 +608,7 @@ public void PutUnmanaged(T value) where T : unmanaged /// /// Writes a nullable value of type into the internal byte buffer at the current position, - /// first writing a indicating whether the value is present, + /// first writing a indicating whether the value is present, /// and then writing the value itself if it exists.
    Advances the position by 1 byte for the presence flag plus /// the size of if the value is present. ///
    @@ -634,7 +634,7 @@ public void PutNullableUnmanaged(T? value) where T : unmanaged /// /// An unmanaged enum type to write. /// The enum value to write. - public void PutEnum(T value) where T : unmanaged, Enum + public unsafe void PutEnum(T value) where T : unmanaged, Enum { var size = sizeof(T); if (_autoResize) From d38944864c23c18ebe35c0e542f60046e177c16e Mon Sep 17 00:00:00 2001 From: RevenantX Date: Sun, 22 Mar 2026 12:55:25 +0200 Subject: [PATCH 131/200] update docs --- docs/api/LiteNetLib.ConnectionRequest.html | 352 +------- .../api/LiteNetLib.ILiteNetEventListener.html | 6 +- .../api/LiteNetLib.LiteConnectionRequest.html | 493 +++++++++++ docs/api/LiteNetLib.LiteNetManager.html | 53 +- .../LiteNetLib.NetConnectRequestPacket.html | 270 ++++++ docs/api/LiteNetLib.NetEvent.html | 4 +- docs/api/LiteNetLib.NetManager.html | 57 +- docs/api/LiteNetLib.NetPacketReader.html | 15 + docs/api/LiteNetLib.Utils.NetDataReader.html | 816 ++++++++++++++---- docs/api/LiteNetLib.Utils.NetDataWriter.html | 580 ++++++++++--- docs/api/LiteNetLib.html | 4 + docs/api/toc.html | 6 + docs/api/toc.json | 2 +- docs/manifest.json | 28 + docs/xrefmap.yml | 515 ++++++++--- 15 files changed, 2475 insertions(+), 726 deletions(-) create mode 100644 docs/api/LiteNetLib.LiteConnectionRequest.html create mode 100644 docs/api/LiteNetLib.NetConnectRequestPacket.html diff --git a/docs/api/LiteNetLib.ConnectionRequest.html b/docs/api/LiteNetLib.ConnectionRequest.html index a0db2405..9b89b5ca 100644 --- a/docs/api/LiteNetLib.ConnectionRequest.html +++ b/docs/api/LiteNetLib.ConnectionRequest.html @@ -76,79 +76,62 @@

    Inheritance
    object
    -
    ConnectionRequest
    + +
    ConnectionRequest
    + +
    Namespace: LiteNetLib
    Assembly: LiteNetLib.dll
    Syntax
    -
    public class ConnectionRequest
    -
    -

    Fields -

    - - -

    RemoteEndPoint

    -
    -
    -
    Declaration
    -
    -
    public readonly IPEndPoint RemoteEndPoint
    -
    -
    Field Value
    - - - - - - - - - - - - - -
    TypeDescription
    IPEndPoint
    -

    Properties -

    - - - -

    Data

    -
    -
    -
    Declaration
    -
    -
    public NetDataReader Data { get; }
    +
    public class ConnectionRequest : LiteConnectionRequest
    -
    Property Value
    - - - - - - - - - - - - - -
    TypeDescription
    NetDataReader

    Methods

    Accept()

    -

    Accept connection and get new NetPeer as result

    -
    +
    Declaration
    -
    public LiteNetPeer Accept()
    +
    public NetPeer Accept()
    Returns
    @@ -160,9 +143,8 @@
    Returns
    - - + +
    LiteNetPeer

    Connected NetPeer

    -
    NetPeer
    @@ -174,7 +156,7 @@

    Declaration
    -
    public LiteNetPeer AcceptIfKey(string key)
    +
    public NetPeer AcceptIfKey(string key)
    Parameters
    @@ -203,251 +185,7 @@
    Returns
    - - - - -
    LiteNetPeer
    - - - -

    Reject()

    -
    -
    -
    Declaration
    -
    -
    public void Reject()
    -
    - - - -

    Reject(NetDataWriter)

    -
    -
    -
    Declaration
    -
    -
    public void Reject(NetDataWriter rejectData)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    NetDataWriterrejectData
    - - - -

    Reject(byte[])

    -
    -
    -
    Declaration
    -
    -
    public void Reject(byte[] rejectData)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    byte[]rejectData
    - - - -

    Reject(byte[], int, int)

    -
    -
    -
    Declaration
    -
    -
    public void Reject(byte[] rejectData, int start, int length)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - - - - - - - - - - - -
    TypeNameDescription
    byte[]rejectData
    intstart
    intlength
    - - - -

    Reject(byte[], int, int, bool)

    -
    -
    -
    Declaration
    -
    -
    public void Reject(byte[] rejectData, int start, int length, bool force)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    TypeNameDescription
    byte[]rejectData
    intstart
    intlength
    boolforce
    - - - -

    RejectForce()

    -
    -
    -
    Declaration
    -
    -
    public void RejectForce()
    -
    - - - -

    RejectForce(NetDataWriter)

    -
    -
    -
    Declaration
    -
    -
    public void RejectForce(NetDataWriter rejectData)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    NetDataWriterrejectData
    - - - -

    RejectForce(byte[])

    -
    -
    -
    Declaration
    -
    -
    public void RejectForce(byte[] rejectData)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - -
    TypeNameDescription
    byte[]rejectData
    - - - -

    RejectForce(byte[], int, int)

    -
    -
    -
    Declaration
    -
    -
    public void RejectForce(byte[] rejectData, int start, int length)
    -
    -
    Parameters
    - - - - - - - - - - - - - - - - - - - - - - + diff --git a/docs/api/LiteNetLib.ILiteNetEventListener.html b/docs/api/LiteNetLib.ILiteNetEventListener.html index b67706f5..09fbcb96 100644 --- a/docs/api/LiteNetLib.ILiteNetEventListener.html +++ b/docs/api/LiteNetLib.ILiteNetEventListener.html @@ -85,13 +85,13 @@

    Methods -

    OnConnectionRequest(ConnectionRequest)

    +

    OnConnectionRequest(LiteConnectionRequest)

    On peer connection requested

    Declaration
    -
    void OnConnectionRequest(ConnectionRequest request)
    +
    void OnConnectionRequest(LiteConnectionRequest request)
    Parameters
    TypeNameDescription
    byte[]rejectData
    intstart
    intlengthNetPeer
    @@ -104,7 +104,7 @@
    Parameters
    - + diff --git a/docs/api/LiteNetLib.LiteConnectionRequest.html b/docs/api/LiteNetLib.LiteConnectionRequest.html new file mode 100644 index 00000000..6eb76992 --- /dev/null +++ b/docs/api/LiteNetLib.LiteConnectionRequest.html @@ -0,0 +1,493 @@ + + + + + + + + Class LiteConnectionRequest + + + + + + + + + + + + + + + +
    +
    + + + + +
    +
    ConnectionRequestLiteConnectionRequest request

    Request information (EndPoint, internal id, additional data)

    + + + + + + + + + + + + +
    TypeDescription
    IPEndPoint
    +

    Properties +

    + + + +

    Data

    +
    +
    +
    Declaration
    +
    +
    public NetDataReader Data { get; }
    +
    +
    Property Value
    + + + + + + + + + + + + + +
    TypeDescription
    NetDataReader
    +

    Methods +

    + + + +

    Accept()

    +

    Accept connection and get new NetPeer as result

    +
    +
    +
    Declaration
    +
    +
    public LiteNetPeer Accept()
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    LiteNetPeer

    Connected NetPeer

    +
    + + + +

    AcceptIfKey(string)

    +
    +
    +
    Declaration
    +
    +
    public LiteNetPeer AcceptIfKey(string key)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    stringkey
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    LiteNetPeer
    + + + +

    Reject()

    +
    +
    +
    Declaration
    +
    +
    public void Reject()
    +
    + + + +

    Reject(NetDataWriter)

    +
    +
    +
    Declaration
    +
    +
    public void Reject(NetDataWriter rejectData)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    NetDataWriterrejectData
    + + + +

    Reject(byte[])

    +
    +
    +
    Declaration
    +
    +
    public void Reject(byte[] rejectData)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]rejectData
    + + + +

    Reject(byte[], int, int)

    +
    +
    +
    Declaration
    +
    +
    public void Reject(byte[] rejectData, int start, int length)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]rejectData
    intstart
    intlength
    + + + +

    Reject(byte[], int, int, bool)

    +
    +
    +
    Declaration
    +
    +
    public void Reject(byte[] rejectData, int start, int length, bool force)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]rejectData
    intstart
    intlength
    boolforce
    + + + +

    RejectForce()

    +
    +
    +
    Declaration
    +
    +
    public void RejectForce()
    +
    + + + +

    RejectForce(NetDataWriter)

    +
    +
    +
    Declaration
    +
    +
    public void RejectForce(NetDataWriter rejectData)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    NetDataWriterrejectData
    + + + +

    RejectForce(byte[])

    +
    +
    +
    Declaration
    +
    +
    public void RejectForce(byte[] rejectData)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]rejectData
    + + + +

    RejectForce(byte[], int, int)

    +
    +
    +
    Declaration
    +
    +
    public void RejectForce(byte[] rejectData, int start, int length)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    byte[]rejectData
    intstart
    intlength
    + + + + + + + + + + + + + + + + diff --git a/docs/api/LiteNetLib.LiteNetManager.html b/docs/api/LiteNetLib.LiteNetManager.html index 97b3162b..cc9bd602 100644 --- a/docs/api/LiteNetLib.LiteNetManager.html +++ b/docs/api/LiteNetLib.LiteNetManager.html @@ -1625,13 +1625,60 @@
    Returns
    + +

    CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket)

    +
    +
    +
    Declaration
    +
    +
    protected virtual LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    IPEndPointremoteEndPoint
    NetConnectRequestPacketrequestPacket
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    LiteConnectionRequest
    + + -

    CreateIncomingPeer(ConnectionRequest, int)

    +

    CreateIncomingPeer(LiteConnectionRequest, int)

    Declaration
    -
    protected virtual LiteNetPeer CreateIncomingPeer(ConnectionRequest request, int id)
    +
    protected virtual LiteNetPeer CreateIncomingPeer(LiteConnectionRequest request, int id)
    Parameters
    @@ -1644,7 +1691,7 @@
    Parameters
    - + diff --git a/docs/api/LiteNetLib.NetConnectRequestPacket.html b/docs/api/LiteNetLib.NetConnectRequestPacket.html new file mode 100644 index 00000000..c39a3bde --- /dev/null +++ b/docs/api/LiteNetLib.NetConnectRequestPacket.html @@ -0,0 +1,270 @@ + + + + + + + + Class NetConnectRequestPacket + + + + + + + + + + + + + + + +
    +
    + + + + +
    +
    ConnectionRequestLiteConnectionRequest request
    + + + + + + + + + + + + +
    TypeDescription
    byte
    + + +

    ConnectionTime

    +
    +
    +
    Declaration
    +
    +
    public readonly long ConnectionTime
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    long
    + + +

    Data

    +
    +
    +
    Declaration
    +
    +
    public readonly NetDataReader Data
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    NetDataReader
    + + +

    HeaderSize

    +
    +
    +
    Declaration
    +
    +
    public const int HeaderSize = 18
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    int
    + + +

    PeerId

    +
    +
    +
    Declaration
    +
    +
    public readonly int PeerId
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    int
    + + +

    TargetAddress

    +
    +
    +
    Declaration
    +
    +
    public readonly byte[] TargetAddress
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    byte[]
    + + + + + + + + + + + + + + + + diff --git a/docs/api/LiteNetLib.NetEvent.html b/docs/api/LiteNetLib.NetEvent.html index 98a9e57e..bea06f3b 100644 --- a/docs/api/LiteNetLib.NetEvent.html +++ b/docs/api/LiteNetLib.NetEvent.html @@ -147,7 +147,7 @@

    Declaration
    -
    public ConnectionRequest ConnectionRequest
    +
    public LiteConnectionRequest ConnectionRequest
    Field Value
    @@ -159,7 +159,7 @@
    Field Value
    - + diff --git a/docs/api/LiteNetLib.NetManager.html b/docs/api/LiteNetLib.NetManager.html index 79ec6f88..86c94fa8 100644 --- a/docs/api/LiteNetLib.NetManager.html +++ b/docs/api/LiteNetLib.NetManager.html @@ -789,13 +789,62 @@
    Exceptions
    ConnectionRequestLiteConnectionRequest
    + +

    CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket)

    +
    +
    +
    Declaration
    +
    +
    protected override LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + + + + + + +
    TypeNameDescription
    IPEndPointremoteEndPoint
    NetConnectRequestPacketrequestPacket
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    LiteConnectionRequest
    +
    Overrides
    + + + -

    CreateIncomingPeer(ConnectionRequest, int)

    +

    CreateIncomingPeer(LiteConnectionRequest, int)

    Declaration
    -
    protected override LiteNetPeer CreateIncomingPeer(ConnectionRequest request, int id)
    +
    protected override LiteNetPeer CreateIncomingPeer(LiteConnectionRequest request, int id)
    Parameters
    @@ -808,7 +857,7 @@
    Parameters
    - + @@ -835,7 +884,7 @@
    Returns
    ConnectionRequestLiteConnectionRequest request
    Overrides
    - + diff --git a/docs/api/LiteNetLib.NetPacketReader.html b/docs/api/LiteNetLib.NetPacketReader.html index 59159508..a2634d2c 100644 --- a/docs/api/LiteNetLib.NetPacketReader.html +++ b/docs/api/LiteNetLib.NetPacketReader.html @@ -183,6 +183,9 @@
    Inherited Members
    + @@ -300,6 +303,15 @@
    Inherited Members
    + + + @@ -342,6 +354,9 @@
    Inherited Members
    + diff --git a/docs/api/LiteNetLib.Utils.NetDataReader.html b/docs/api/LiteNetLib.Utils.NetDataReader.html index 477f7dc5..4b8e7acb 100644 --- a/docs/api/LiteNetLib.Utils.NetDataReader.html +++ b/docs/api/LiteNetLib.Utils.NetDataReader.html @@ -292,7 +292,8 @@

    Properties

    AvailableBytes

    -
    +

    Gets the number of bytes remaining to be read.

    +
    Declaration
    @@ -317,7 +318,8 @@
    Property Value

    EndOfData

    -
    +

    Gets a value indicating whether the Position has reached the end of the data.

    +
    Declaration
    @@ -342,7 +344,8 @@
    Property Value

    IsNull

    -
    +

    Gets a value indicating whether the internal data buffer is null.

    +
    Declaration
    @@ -367,7 +370,8 @@
    Property Value

    Position

    -
    +

    Gets the current read position within the buffer.

    +
    Declaration
    @@ -392,7 +396,8 @@
    Property Value

    RawData

    -
    +

    Gets the internal byte array containing the raw network data.

    +
    Declaration
    @@ -417,7 +422,8 @@
    Property Value

    RawDataSize

    -
    +

    Gets the total size of the RawData buffer.

    +
    Declaration
    @@ -442,7 +448,8 @@
    Property Value

    UserDataOffset

    -
    +

    Gets the starting offset of the user payload within the RawData.

    +
    Declaration
    @@ -467,7 +474,8 @@
    Property Value

    UserDataSize

    -
    +

    Gets the size of the user payload excluding the initial UserDataOffset.

    +
    Declaration
    @@ -494,7 +502,8 @@

    Methods

    Clear()

    -
    +

    Clears the reader state and releases the reference to the internal buffer.

    +
    Declaration
    @@ -504,7 +513,8 @@
    Declaration

    Get(out bool)

    -
    +

    Reads a bool and assigns it to result.

    +
    Declaration
    @@ -531,7 +541,8 @@
    Parameters

    Get(out byte)

    -
    +

    Reads a byte and assigns it to result.

    +
    Declaration
    @@ -558,7 +569,8 @@
    Parameters

    Get(out char)

    -
    +

    Reads a char and assigns it to result.

    +
    Declaration
    @@ -585,7 +597,8 @@
    Parameters

    Get(out double)

    -
    +

    Reads a double and assigns it to result.

    +
    Declaration
    @@ -612,7 +625,8 @@
    Parameters

    Get(out Guid)

    -
    +

    Reads a Guid and assigns it to result.

    +
    Declaration
    @@ -639,7 +653,8 @@
    Parameters

    Get(out short)

    -
    +

    Reads a short and assigns it to result.

    +
    Declaration
    @@ -666,7 +681,8 @@
    Parameters

    Get(out int)

    -
    +

    Reads an int and assigns it to result.

    +
    Declaration
    @@ -693,7 +709,8 @@
    Parameters

    Get(out long)

    -
    +

    Reads a long and assigns it to result.

    +
    Declaration
    @@ -720,7 +737,8 @@
    Parameters

    Get(out IPEndPoint)

    -
    +

    Deserializes an IPEndPoint and assigns it to the result parameter.

    +
    Declaration
    @@ -739,7 +757,8 @@
    Parameters
    IPEndPoint result - +

    The deserialized IPEndPoint output.

    + @@ -747,7 +766,8 @@
    Parameters

    Get(out sbyte)

    -
    +

    Reads an sbyte and assigns it to result.

    +
    Declaration
    @@ -774,7 +794,8 @@
    Parameters

    Get(out float)

    -
    +

    Reads a float and assigns it to result.

    +
    Declaration
    @@ -801,7 +822,8 @@
    Parameters

    Get(out string)

    -
    +

    Reads a string and assigns it to result.

    +
    Declaration
    @@ -828,7 +850,8 @@
    Parameters

    Get(out string, int)

    -
    +

    Reads a string with a length limit and assigns it to result.

    +
    Declaration
    @@ -860,7 +883,8 @@
    Parameters

    Get(out ushort)

    -
    +

    Reads a ushort and assigns it to result.

    +
    Declaration
    @@ -887,7 +911,8 @@
    Parameters

    Get(out uint)

    -
    +

    Reads a uint and assigns it to result.

    +
    Declaration
    @@ -914,7 +939,8 @@
    Parameters

    Get(out ulong)

    -
    +

    Reads a ulong and assigns it to result.

    +
    Declaration
    @@ -941,7 +967,8 @@
    Parameters

    GetArray<T>()

    -
    +

    Reads an array of objects implementing INetSerializable.

    +
    Declaration
    @@ -958,7 +985,8 @@
    Returns
    T[] - +

    A new array of type T.

    + @@ -973,7 +1001,8 @@
    Type Parameters
    T - +

    A type with a parameterless constructor implementing INetSerializable.

    + @@ -981,7 +1010,8 @@
    Type Parameters

    GetArray<T>(Func<T>)

    -
    +

    Reads an array of objects implementing INetSerializable using a specific constructor.

    +
    Declaration
    @@ -1000,7 +1030,8 @@
    Parameters
    Func<T> constructor - +

    The factory delegate used to create instances.

    + @@ -1015,7 +1046,8 @@
    Returns
    T[] - +

    A new array of type T.

    + @@ -1030,7 +1062,8 @@
    Type Parameters
    T - +

    A class type implementing INetSerializable.

    + @@ -1038,7 +1071,8 @@
    Type Parameters

    GetArray<T>(ushort)

    -
    +

    Reads an array of values by performing a direct memory copy.

    +
    Declaration
    @@ -1057,7 +1091,8 @@
    Parameters
    ushort size - +

    The size of a single element in bytes.

    + @@ -1072,7 +1107,8 @@
    Returns
    T[] - +

    A new array of type T.

    + @@ -1087,7 +1123,8 @@
    Type Parameters
    T - +

    The element type.

    + @@ -1095,7 +1132,8 @@
    Type Parameters

    GetBool()

    -
    +

    Reads a bool value from the current position.

    +
    Declaration
    @@ -1112,7 +1150,8 @@
    Returns
    bool - +

    true if the byte is 1; otherwise, false.

    + @@ -1120,7 +1159,8 @@
    Returns

    GetBoolArray()

    -
    +

    Reads an array of bool values.

    +
    Declaration
    @@ -1145,7 +1185,8 @@
    Returns

    GetByte()

    -
    +

    Reads the next byte from the buffer.

    +
    Declaration
    @@ -1170,7 +1211,8 @@
    Returns

    GetBytes(byte[], int)

    -
    +

    Copies a specified number of bytes into a destination array starting at index 0.

    +
    Declaration
    @@ -1189,12 +1231,14 @@
    Parameters
    byte[] destination - +

    The array to copy data into.

    + int count - +

    The number of bytes to read.

    + @@ -1202,7 +1246,8 @@
    Parameters

    GetBytes(byte[], int, int)

    -
    +

    Copies a specified number of bytes into a destination array at a specific offset.

    +
    Declaration
    @@ -1221,17 +1266,20 @@
    Parameters
    byte[] destination - +

    The array to copy data into.

    + int start - +

    The starting index in the destination array.

    + int count - +

    The number of bytes to read.

    + @@ -1239,7 +1287,8 @@
    Parameters

    GetBytesSegment(int)

    -
    +

    Gets an ArraySegment<T> of bytes from the current position.

    +
    Declaration
    @@ -1258,7 +1307,8 @@
    Parameters
    int count - +

    The number of bytes to include in the segment.

    + @@ -1273,7 +1323,8 @@
    Returns
    ArraySegment<byte> - +

    An ArraySegment<T> wrapping the internal buffer.

    + @@ -1281,7 +1332,8 @@
    Returns

    GetBytesWithLength()

    -
    +

    Reads a byte array prefixed with its ushort length.

    +
    Declaration
    @@ -1298,7 +1350,8 @@
    Returns
    byte[] - +

    A new byte array.

    + @@ -1306,7 +1359,8 @@
    Returns

    GetChar()

    -
    +

    Reads a char value as a 2-byte ushort.

    +
    Declaration
    @@ -1331,7 +1385,8 @@
    Returns

    GetDouble()

    -
    +

    Reads a double value using unmanaged memory access.

    +
    Declaration
    @@ -1356,7 +1411,8 @@
    Returns

    GetDoubleArray()

    -
    +

    Reads an array of double values.

    +
    Declaration
    @@ -1379,9 +1435,54 @@
    Returns
    + +

    GetEnum<T>()

    +

    Reads an enum value of type T from the internal data buffer at the current position.
    +Advances the position by the size of T.

    +
    +
    +
    Declaration
    +
    +
    public T GetEnum<T>() where T : unmanaged, Enum
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T

    The enum value read from the buffer.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged enum type to read.

    +
    + +

    GetFloat()

    -
    +

    Reads a float value using unmanaged memory access.

    +
    Declaration
    @@ -1406,7 +1507,8 @@
    Returns

    GetFloatArray()

    -
    +

    Reads an array of float values.

    +
    Declaration
    @@ -1431,7 +1533,8 @@
    Returns

    GetGuid()

    -
    +

    Reads a 16-byte Guid.

    +
    Declaration
    @@ -1448,7 +1551,8 @@
    Returns
    Guid - +

    The deserialized Guid.

    + @@ -1456,7 +1560,8 @@
    Returns

    GetIPEndPoint()

    -
    +

    Reads an IPEndPoint from the current Position.

    +
    Declaration
    @@ -1473,15 +1578,21 @@
    Returns
    IPEndPoint - +

    The deserialized IPEndPoint.

    + +
    Remarks
    +

    Reads a byte to determine the AddressFamily (0 for IPv4, 1 for IPv6), +followed by the address bytes and a 2-byte ushort port.

    +

    GetInt()

    -
    +

    Reads an int value using unmanaged memory access.

    +
    Declaration
    @@ -1506,7 +1617,8 @@
    Returns

    GetIntArray()

    -
    +

    Reads an array of int values.

    +
    Declaration
    @@ -1531,7 +1643,8 @@
    Returns

    GetLargeString()

    -
    +

    Reads a string prefixed with a 4-byte int length header.

    +
    Declaration
    @@ -1548,7 +1661,8 @@
    Returns
    string - +

    The deserialized string.

    + @@ -1556,7 +1670,8 @@
    Returns

    GetLong()

    -
    +

    Reads a long value using unmanaged memory access.

    +
    Declaration
    @@ -1581,7 +1696,8 @@
    Returns

    GetLongArray()

    -
    +

    Reads an array of long values.

    +
    Declaration
    @@ -1604,9 +1720,72 @@
    Returns
    + +

    GetNullableUnmanaged<T>()

    +

    Reads a nullable value of type T from the internal byte buffer at the current position, +first reading a bool indicating whether the value is present, +and then reading the value itself if it exists.
    +Advances the position by 1 byte for the presence flag plus the size of T if the value is present.

    +
    +
    +
    Declaration
    +
    +
    public T? GetNullableUnmanaged<T>() where T : unmanaged
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T?

    The nullable value of type T read from the buffer. +Returns null if the presence flag indicates no value.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type to read from the buffer.

    +
    +
    Exceptions
    + + + + + + + + + + + + + +
    TypeCondition
    IndexOutOfRangeException
    + +

    GetRemainingBytes()

    -
    +

    Reads all remaining bytes and returns them as a new array.

    +
    Declaration
    @@ -1623,15 +1802,20 @@
    Returns
    byte[] - +

    A new byte array containing the remaining data.

    + +
    Remarks
    +

    This method performs a heap allocation and advances the Position to the end of the data.

    +

    GetRemainingBytesMemory()

    -
    +

    Returns a ReadOnlyMemory<T> of bytes containing all remaining data.

    +
    Declaration
    @@ -1648,7 +1832,8 @@
    Returns
    ReadOnlyMemory<byte> - +

    A ReadOnlyMemory<T> from the current Position to the end of the buffer.

    + @@ -1656,7 +1841,8 @@
    Returns

    GetRemainingBytesSegment()

    -
    +

    Gets an ArraySegment<T> containing all remaining bytes.

    +
    Declaration
    @@ -1673,7 +1859,8 @@
    Returns
    ArraySegment<byte> - +

    An ArraySegment<T> from the current position to the end of the data.

    + @@ -1681,7 +1868,8 @@
    Returns

    GetRemainingBytesSpan()

    -
    +

    Returns a ReadOnlySpan<T> of bytes containing all remaining data.

    +
    Declaration
    @@ -1698,7 +1886,8 @@
    Returns
    ReadOnlySpan<byte> - +

    A ReadOnlySpan<T> from the current Position to the end of the buffer.

    + @@ -1706,7 +1895,8 @@
    Returns

    GetSByte()

    -
    +

    Reads the next sbyte from the buffer.

    +
    Declaration
    @@ -1731,7 +1921,8 @@
    Returns

    GetSBytesWithLength()

    -
    +

    Reads an sbyte array prefixed with its ushort length.

    +
    Declaration
    @@ -1748,7 +1939,8 @@
    Returns
    sbyte[] - +

    A new sbyte array.

    + @@ -1756,7 +1948,8 @@
    Returns

    GetShort()

    -
    +

    Reads a short value using unmanaged memory access.

    +
    Declaration
    @@ -1781,7 +1974,8 @@
    Returns

    GetShortArray()

    -
    +

    Reads an array of short values.

    +
    Declaration
    @@ -1806,7 +2000,8 @@
    Returns

    GetString()

    -
    +

    Reads a string from the current position.

    +
    Declaration
    @@ -1823,7 +2018,8 @@
    Returns
    string - +

    The deserialized string.

    + @@ -1831,7 +2027,7 @@
    Returns

    GetString(int)

    -

    Note that "maxLength" only limits the number of characters in a string, not its size in bytes.

    +

    Reads a string with a maximum character limit.

    Declaration
    @@ -1851,7 +2047,8 @@
    Parameters
    int maxLength - +

    The maximum allowed character count.

    + @@ -1866,16 +2063,20 @@
    Returns
    string -

    "string.Empty" if value > "maxLength"

    +

    The deserialized string, or Empty if the character count exceeds maxLength.

    +
    Remarks
    +

    Note that maxLength limits the number of characters, not the total size in bytes.

    +

    GetStringArray()

    -
    +

    Reads an array of string values.

    +
    Declaration
    @@ -1892,16 +2093,19 @@
    Returns
    string[] - +

    A new string array.

    + +
    Remarks
    +

    Reads a 2-byte ushort length header followed by each string element.

    +

    GetStringArray(int)

    -

    Note that "maxStringLength" only limits the number of characters in a string, not its size in bytes. -Strings that exceed this parameter are returned as empty

    +

    Reads an array of string values with a maximum character limit per element.

    Declaration
    @@ -1921,7 +2125,8 @@
    Parameters
    int maxStringLength - +

    The maximum number of characters allowed per string.

    + @@ -1936,15 +2141,20 @@
    Returns
    string[] - +

    A new string array.

    + +
    Remarks
    +

    Strings exceeding maxStringLength are returned as Empty.

    +

    GetUInt()

    -
    +

    Reads a uint value using unmanaged memory access.

    +
    Declaration
    @@ -1969,7 +2179,8 @@
    Returns

    GetUIntArray()

    -
    +

    Reads an array of uint values.

    +
    Declaration
    @@ -1994,7 +2205,8 @@
    Returns

    GetULong()

    -
    +

    Reads a ulong value using unmanaged memory access.

    +
    Declaration
    @@ -2019,7 +2231,8 @@
    Returns

    GetULongArray()

    -
    +

    Reads an array of ulong values.

    +
    Declaration
    @@ -2044,7 +2257,8 @@
    Returns

    GetUShort()

    -
    +

    Reads a ushort value using unmanaged memory access.

    +
    Declaration
    @@ -2069,7 +2283,8 @@
    Returns

    GetUShortArray()

    -
    +

    Reads an array of ushort values.

    +
    Declaration
    @@ -2092,9 +2307,112 @@
    Returns
    + +

    GetUnmanagedArray<T>()

    +

    Reads an array of unmanaged values prefixed by a ushort length.

    +
    +
    +
    Declaration
    +
    +
    public T[] GetUnmanagedArray<T>() where T : unmanaged
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T[]

    A new array of type T.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged type.

    +
    + + + +

    GetUnmanaged<T>()

    +

    Reads a value of type T from the internal byte buffer at the current position, +advancing the position by the size of T.

    +
    +
    +
    Declaration
    +
    +
    public T GetUnmanaged<T>() where T : unmanaged
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T

    The value of type T read from the buffer.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type to read from the buffer.

    +
    +
    Exceptions
    + + + + + + + + + + + + + +
    TypeCondition
    IndexOutOfRangeException
    + +

    Get<T>()

    -
    +

    Deserializes a struct that implements INetSerializable.

    +
    Declaration
    @@ -2111,7 +2429,8 @@
    Returns
    T - +

    The deserialized struct.

    + @@ -2126,7 +2445,8 @@
    Type Parameters
    T - +

    A struct type implementing INetSerializable.

    + @@ -2134,7 +2454,8 @@
    Type Parameters

    Get<T>(Func<T>)

    -
    +

    Deserializes a class that implements INetSerializable using a provided constructor.

    +
    Declaration
    @@ -2153,7 +2474,8 @@
    Parameters
    Func<T> constructor - +

    The factory delegate used to instantiate the class.

    + @@ -2168,7 +2490,8 @@
    Returns
    T - +

    A new instance of T.

    + @@ -2183,7 +2506,8 @@
    Type Parameters
    T - +

    A class type implementing INetSerializable.

    + @@ -2191,7 +2515,8 @@
    Type Parameters

    Get<T>(out T)

    -
    +

    Deserializes a struct that implements INetSerializable.

    +
    Declaration
    @@ -2210,7 +2535,8 @@
    Parameters
    T result - +

    The deserialized struct output.

    + @@ -2225,7 +2551,8 @@
    Type Parameters
    T - +

    A struct type implementing INetSerializable.

    + @@ -2233,7 +2560,8 @@
    Type Parameters

    Get<T>(out T, Func<T>)

    -
    +

    Deserializes a that implements INetSerializable using a provided constructor.

    +
    Declaration
    @@ -2252,12 +2580,14 @@
    Parameters
    T result - +

    The deserialized class instance output.

    + Func<T> constructor - +

    A factory delegate used to instantiate the class.

    + @@ -2272,7 +2602,8 @@
    Type Parameters
    T - +

    A class type implementing INetSerializable.

    + @@ -2280,7 +2611,8 @@
    Type Parameters

    PeekBool()

    -
    +

    Reads the bool at the current position without advancing the Position.

    +
    Declaration
    @@ -2305,7 +2637,8 @@
    Returns

    PeekByte()

    -
    +

    Reads the byte at the current position without advancing the Position.

    +
    Declaration
    @@ -2330,7 +2663,8 @@
    Returns

    PeekChar()

    -
    +

    Reads the char at the current position without advancing the Position.

    +
    Declaration
    @@ -2355,7 +2689,8 @@
    Returns

    PeekDouble()

    -
    +

    Reads the double at the current position without advancing the Position.

    +
    Declaration
    @@ -2380,7 +2715,8 @@
    Returns

    PeekFloat()

    -
    +

    Reads the float at the current position without advancing the Position.

    +
    Declaration
    @@ -2405,7 +2741,8 @@
    Returns

    PeekInt()

    -
    +

    Reads the int at the current position without advancing the Position.

    +
    Declaration
    @@ -2430,7 +2767,8 @@
    Returns

    PeekLong()

    -
    +

    Reads the long at the current position without advancing the Position.

    +
    Declaration
    @@ -2455,7 +2793,8 @@
    Returns

    PeekSByte()

    -
    +

    Reads the sbyte at the current position without advancing the Position.

    +
    Declaration
    @@ -2480,7 +2819,8 @@
    Returns

    PeekShort()

    -
    +

    Reads the short at the current position without advancing the Position.

    +
    Declaration
    @@ -2505,7 +2845,8 @@
    Returns

    PeekString()

    -
    +

    Reads a string without advancing the Position.

    +
    Declaration
    @@ -2530,7 +2871,7 @@
    Returns

    PeekString(int)

    -

    Note that "maxLength" only limits the number of characters in a string, not its size in bytes.

    +

    Reads a string with a character limit without advancing the Position.

    Declaration
    @@ -2550,7 +2891,8 @@
    Parameters
    int maxLength - +

    Maximum allowed character count.

    + @@ -2569,11 +2911,15 @@
    Returns
    +
    Remarks
    +

    Strings exceeding maxLength are returned as Empty.

    +

    PeekUInt()

    -
    +

    Reads the uint at the current position without advancing the Position.

    +
    Declaration
    @@ -2598,7 +2944,8 @@
    Returns

    PeekULong()

    -
    +

    Reads the ulong at the current position without advancing the Position.

    +
    Declaration
    @@ -2623,7 +2970,8 @@
    Returns

    PeekUShort()

    -
    +

    Reads the ushort at the current position without advancing the Position.

    +
    Declaration
    @@ -2646,9 +2994,53 @@
    Returns
    + +

    PeekUnmanaged<T>()

    +

    Reads an unmanaged value of type T at the current position without advancing the Position.

    +
    +
    +
    Declaration
    +
    +
    public T PeekUnmanaged<T>() where T : unmanaged
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    T

    The value read from the buffer.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type.

    +
    + +

    SetPosition(int)

    -
    +

    Sets the current read Position to a specific index.

    +
    Declaration
    @@ -2667,7 +3059,8 @@
    Parameters
    int position - +

    The index to move the Position to.

    + @@ -2675,7 +3068,8 @@
    Parameters

    SetSource(NetDataWriter)

    -
    +

    Reinitializes the reader using data from a NetDataWriter.

    +
    Declaration
    @@ -2694,7 +3088,8 @@
    Parameters
    NetDataWriter dataWriter - +

    The source NetDataWriter.

    + @@ -2702,7 +3097,8 @@
    Parameters

    SetSource(byte[])

    -
    +

    Reinitializes the reader using a byte array.

    +
    Declaration
    @@ -2721,7 +3117,8 @@
    Parameters
    byte[] source - +

    The source byte array.

    + @@ -2729,7 +3126,8 @@
    Parameters

    SetSource(byte[], int, int)

    -
    +

    Reinitializes the reader using a segment of a byte array.

    +
    Declaration
    @@ -2748,17 +3146,20 @@
    Parameters
    byte[] source - +

    The source byte array.

    + int offset - +

    The starting index for reading.

    + int maxSize - +

    The total number of bytes available to read from the source.

    + @@ -2766,7 +3167,8 @@
    Parameters

    SkipBytes(int)

    -
    +

    Advances the Position by the specified count.

    +
    Declaration
    @@ -2785,7 +3187,8 @@
    Parameters
    int count - +

    The number of bytes to skip.

    + @@ -2793,7 +3196,8 @@
    Parameters

    TryGetBool(out bool)

    -
    +

    Attempts to read a bool without throwing an exception.

    +
    Declaration
    @@ -2812,7 +3216,8 @@
    Parameters
    bool result - +

    The deserialized bool, or false if failed.

    + @@ -2827,7 +3232,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -2835,7 +3241,8 @@
    Returns

    TryGetByte(out byte)

    -
    +

    Attempts to read a byte without throwing an exception.

    +
    Declaration
    @@ -2854,7 +3261,8 @@
    Parameters
    byte result - +

    The deserialized byte, or 0 if failed.

    + @@ -2869,7 +3277,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -2877,7 +3286,8 @@
    Returns

    TryGetBytesWithLength(out byte[])

    -
    +

    Attempts to read a byte array with a length header without throwing an exception.

    +
    Declaration
    @@ -2896,7 +3306,8 @@
    Parameters
    byte[] result - +

    The deserialized byte array, or null if failed.

    + @@ -2911,7 +3322,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -2919,7 +3331,8 @@
    Returns

    TryGetChar(out char)

    -
    +

    Attempts to read a char without throwing an exception.

    +
    Declaration
    @@ -2938,7 +3351,8 @@
    Parameters
    char result - +

    The deserialized char, or '\0' if failed.

    + @@ -2953,7 +3367,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -2961,7 +3376,8 @@
    Returns

    TryGetDouble(out double)

    -
    +

    Attempts to read a double without throwing an exception.

    +
    Declaration
    @@ -2980,7 +3396,8 @@
    Parameters
    double result - +

    The deserialized double, or 0 if failed.

    + @@ -2995,7 +3412,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3003,7 +3421,8 @@
    Returns

    TryGetFloat(out float)

    -
    +

    Attempts to read a float without throwing an exception.

    +
    Declaration
    @@ -3022,7 +3441,8 @@
    Parameters
    float result - +

    The deserialized float, or 0 if failed.

    + @@ -3037,7 +3457,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3045,7 +3466,8 @@
    Returns

    TryGetInt(out int)

    -
    +

    Attempts to read an int without throwing an exception.

    +
    Declaration
    @@ -3064,7 +3486,8 @@
    Parameters
    int result - +

    The deserialized int, or 0 if failed.

    + @@ -3079,7 +3502,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3087,7 +3511,8 @@
    Returns

    TryGetLong(out long)

    -
    +

    Attempts to read a long without throwing an exception.

    +
    Declaration
    @@ -3106,7 +3531,8 @@
    Parameters
    long result - +

    The deserialized long, or 0 if failed.

    + @@ -3121,7 +3547,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3129,7 +3556,8 @@
    Returns

    TryGetSByte(out sbyte)

    -
    +

    Attempts to read an sbyte without throwing an exception.

    +
    Declaration
    @@ -3148,7 +3576,8 @@
    Parameters
    sbyte result - +

    The deserialized sbyte, or 0 if failed.

    + @@ -3163,7 +3592,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3171,7 +3601,8 @@
    Returns

    TryGetShort(out short)

    -
    +

    Attempts to read a short without throwing an exception.

    +
    Declaration
    @@ -3190,7 +3621,8 @@
    Parameters
    short result - +

    The deserialized short, or 0 if failed.

    + @@ -3205,7 +3637,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3213,7 +3646,8 @@
    Returns

    TryGetString(out string)

    -
    +

    Attempts to read a string without throwing an exception.

    +
    Declaration
    @@ -3232,7 +3666,8 @@
    Parameters
    string result - +

    The deserialized string, or null if failed.

    + @@ -3247,7 +3682,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3255,7 +3691,8 @@
    Returns

    TryGetStringArray(out string[])

    -
    +

    Attempts to read a string array without throwing an exception.

    +
    Declaration
    @@ -3274,7 +3711,8 @@
    Parameters
    string[] result - +

    The deserialized string array, or null if failed.

    + @@ -3289,7 +3727,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3297,7 +3736,8 @@
    Returns

    TryGetUInt(out uint)

    -
    +

    Attempts to read a uint without throwing an exception.

    +
    Declaration
    @@ -3316,7 +3756,8 @@
    Parameters
    uint result - +

    The deserialized uint, or 0 if failed.

    + @@ -3331,7 +3772,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3339,7 +3781,8 @@
    Returns

    TryGetULong(out ulong)

    -
    +

    Attempts to read a ulong without throwing an exception.

    +
    Declaration
    @@ -3358,7 +3801,8 @@
    Parameters
    ulong result - +

    The deserialized ulong, or 0 if failed.

    + @@ -3373,7 +3817,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + @@ -3381,7 +3826,8 @@
    Returns

    TryGetUShort(out ushort)

    -
    +

    Attempts to read a ushort without throwing an exception.

    +
    Declaration
    @@ -3400,7 +3846,8 @@
    Parameters
    ushort result - +

    The deserialized ushort, or 0 if failed.

    + @@ -3415,7 +3862,8 @@
    Returns
    bool - +

    true if enough data was available; otherwise, false.

    + diff --git a/docs/api/LiteNetLib.Utils.NetDataWriter.html b/docs/api/LiteNetLib.Utils.NetDataWriter.html index c06d2e85..d24d1d4a 100644 --- a/docs/api/LiteNetLib.Utils.NetDataWriter.html +++ b/docs/api/LiteNetLib.Utils.NetDataWriter.html @@ -211,7 +211,8 @@

    Properties

    Capacity

    -
    +

    Gets the total capacity of the internal byte buffer.

    +
    Declaration
    @@ -228,7 +229,8 @@
    Property Value
    int - +

    The length of the underlying _data array.

    + @@ -236,7 +238,8 @@
    Property Value

    Data

    -
    +

    Gets the underlying byte array used by this writer.

    +
    Declaration
    @@ -253,15 +256,20 @@
    Property Value
    byte[] - +

    The internal _data array.

    + +
    Remarks
    +

    Accessing this directly allows for external manipulation but bypasses bounds checking.

    +

    Length

    -
    +

    Gets the current number of bytes written to the buffer.

    +
    Declaration
    @@ -278,7 +286,8 @@
    Property Value
    int - +

    The current _position.

    + @@ -288,7 +297,8 @@

    Methods

    AsReadOnlySpan()

    -
    +

    Returns a ReadOnlySpan<T> representing the currently used portion of the internal buffer.

    +
    Declaration
    @@ -305,15 +315,21 @@
    Returns
    ReadOnlySpan<byte> - +

    A ReadOnlySpan<T> from index 0 to _position.

    + +
    Remarks
    +

    Provides a high-performance, zero-allocation view of the data. +The span becomes invalid if the internal buffer is resized or if _position changes.

    +

    CopyData()

    -
    +

    Creates a byte array containing the current data from the internal buffer.

    +
    Declaration
    @@ -330,15 +346,20 @@
    Returns
    byte[] - +

    A new byte array of length _position.

    + +
    Remarks
    +

    This method performs a heap allocation and copies the data using BlockCopy(Array, int, Array, int, int).

    +

    EnsureFit(int)

    -
    +

    Ensures the internal buffer can accommodate additionalSize more bytes.

    +
    Declaration
    @@ -357,10 +378,15 @@
    Parameters
    int additionalSize - +

    The number of additional bytes to fit.

    + +
    Remarks
    +

    This checks against the current _position. If the capacity is insufficient, +the buffer grows to either the required size or doubles its current size.

    +
    @@ -514,7 +540,8 @@
    Returns

    FromString(string)

    -
    +

    Creates a new NetDataWriter and serializes a string into it.

    +
    Declaration
    @@ -533,7 +560,8 @@
    Parameters
    string value - +

    The string to serialize.

    + @@ -548,7 +576,8 @@
    Returns
    NetDataWriter - +

    A new NetDataWriter instance containing the serialized string.

    + @@ -556,7 +585,8 @@
    Returns

    Put(bool)

    -
    +

    Serializes a bool value as a single byte.

    +
    Declaration
    @@ -575,7 +605,8 @@
    Parameters
    bool value - +

    The bool value to write.

    + @@ -583,7 +614,8 @@
    Parameters

    Put(byte)

    -
    +

    Serializes a byte value.

    +
    Declaration
    @@ -602,7 +634,8 @@
    Parameters
    byte value - +

    The byte value to write.

    + @@ -610,7 +643,8 @@
    Parameters

    Put(byte[])

    -
    +

    Serializes an entire byte array.

    +
    Declaration
    @@ -629,7 +663,8 @@
    Parameters
    byte[] data - +

    The source array.

    + @@ -637,7 +672,8 @@
    Parameters

    Put(byte[], int, int)

    -
    +

    Serializes a segment of a byte array.

    +
    Declaration
    @@ -656,17 +692,20 @@
    Parameters
    byte[] data - +

    The source array.

    + int offset - +

    The starting index in the source array.

    + int length - +

    The number of bytes to write.

    + @@ -674,7 +713,8 @@
    Parameters

    Put(char)

    -
    +

    Serializes a char value as a ushort.

    +
    Declaration
    @@ -693,7 +733,8 @@
    Parameters
    char value - +

    The char value to write.

    + @@ -701,7 +742,8 @@
    Parameters

    Put(double)

    -
    +

    Serializes a double value.

    +
    Declaration
    @@ -720,7 +762,8 @@
    Parameters
    double value - +

    The double value to write.

    + @@ -728,7 +771,8 @@
    Parameters

    Put(Guid)

    -
    +

    Serializes a Guid value.

    +
    Declaration
    @@ -747,7 +791,8 @@
    Parameters
    Guid value - +

    The Guid value to write.

    + @@ -755,7 +800,8 @@
    Parameters

    Put(short)

    -
    +

    Serializes a short value.

    +
    Declaration
    @@ -774,7 +820,8 @@
    Parameters
    short value - +

    The short value to write.

    + @@ -782,7 +829,8 @@
    Parameters

    Put(int)

    -
    +

    Serializes an int value.

    +
    Declaration
    @@ -801,7 +849,8 @@
    Parameters
    int value - +

    The int value to write.

    + @@ -809,7 +858,8 @@
    Parameters

    Put(long)

    -
    +

    Serializes a long value.

    +
    Declaration
    @@ -828,7 +878,8 @@
    Parameters
    long value - +

    The long value to write.

    + @@ -836,7 +887,8 @@
    Parameters

    Put(IPEndPoint)

    -
    +

    Serializes an IPEndPoint.

    +
    Declaration
    @@ -855,7 +907,27 @@
    Parameters
    IPEndPoint endPoint - +

    The network endpoint to write.

    + + + + +
    Remarks
    +

    Writes a byte (0 for IPv4, 1 for IPv6), followed by the address bytes and a 2-byte ushort port.

    +
    +
    Exceptions
    + + + + + + + + + + +
    TypeCondition
    ArgumentException

    Thrown when the AddressFamily is not InterNetwork or InterNetworkV6.

    +
    @@ -863,7 +935,8 @@
    Parameters

    Put(ReadOnlySpan<byte>)

    -
    +

    Serializes a ReadOnlySpan<T> of bytes to the internal buffer.

    +
    Declaration
    @@ -882,7 +955,8 @@
    Parameters
    ReadOnlySpan<byte> data - +

    The span of data to write.

    + @@ -890,7 +964,8 @@
    Parameters

    Put(sbyte)

    -
    +

    Serializes an sbyte value.

    +
    Declaration
    @@ -909,7 +984,8 @@
    Parameters
    sbyte value - +

    The sbyte value to write.

    + @@ -917,7 +993,8 @@
    Parameters

    Put(float)

    -
    +

    Serializes a float value.

    +
    Declaration
    @@ -936,7 +1013,8 @@
    Parameters
    float value - +

    The float value to write.

    + @@ -944,7 +1022,7 @@
    Parameters

    Put(string, int)

    -

    Note that "maxLength" only limits the number of characters in a string, not its size in bytes.

    +

    Serializes a string using a 2-byte float length header.

    Declaration
    @@ -964,20 +1042,28 @@
    Parameters
    string value - +

    The string to write to the buffer.

    + int maxLength - +

    The maximum number of characters to write. If the string is longer, it will be truncated.
    +A value of 0 indicates no limit.

    + +
    Remarks
    +

    Note that maxLength limits the number of characters, not the total size in bytes.
    +Uses UTF8.

    +

    Put(ushort)

    -
    +

    Serializes a ushort value.

    +
    Declaration
    @@ -996,7 +1082,8 @@
    Parameters
    ushort value - +

    The ushort value to write.

    + @@ -1004,7 +1091,8 @@
    Parameters

    Put(uint)

    -
    +

    Serializes a uint value.

    +
    Declaration
    @@ -1023,7 +1111,8 @@
    Parameters
    uint value - +

    The uint value to write.

    + @@ -1031,7 +1120,8 @@
    Parameters

    Put(ulong)

    -
    +

    Serializes a ulong value.

    +
    Declaration
    @@ -1050,7 +1140,8 @@
    Parameters
    ulong value - +

    The ulong value to write.

    + @@ -1058,7 +1149,8 @@
    Parameters

    PutArray(Array, int)

    -
    +

    Serializes an Array prefixed with a 2-byte ushort length.

    +
    Declaration
    @@ -1077,20 +1169,27 @@
    Parameters
    Array arr - +

    The source array to serialize.

    + int sz - +

    The size of a single element in bytes.

    + +
    Remarks
    +

    If the array is null, a length of 0 is written.
    +The total payload size is calculated as length * sz.

    +

    PutArray(bool[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1117,7 +1216,8 @@
    Parameters

    PutArray(double[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1144,7 +1244,8 @@
    Parameters

    PutArray(short[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1171,7 +1272,8 @@
    Parameters

    PutArray(int[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1198,7 +1300,8 @@
    Parameters

    PutArray(long[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1225,7 +1328,8 @@
    Parameters

    PutArray(float[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1252,7 +1356,8 @@
    Parameters

    PutArray(string[])

    -
    +

    Serializes an array of string values.

    +
    Declaration
    @@ -1271,15 +1376,20 @@
    Parameters
    string[] value - +

    The array of string elements to write.

    + +
    Remarks
    +

    Writes a 2-byte ushort length header followed by each string element.

    +

    PutArray(string[], int)

    -
    +

    Serializes an array of string values with a maximum length constraint per element.

    +
    Declaration
    @@ -1298,12 +1408,14 @@
    Parameters
    string[] value - +

    The array of string elements to write.

    + int strMaxLength - +

    The maximum allowed length for each individual string.

    + @@ -1311,7 +1423,8 @@
    Parameters

    PutArray(ushort[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1338,7 +1451,8 @@
    Parameters

    PutArray(uint[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1365,7 +1479,8 @@
    Parameters

    PutArray(ulong[])

    -
    +

    Serializes an array of unmanaged values to the internal buffer.

    +
    Declaration
    @@ -1392,7 +1507,8 @@
    Parameters

    PutArray<T>(T[])

    -
    +

    Serializes an array of objects implementing INetSerializable.

    +
    Declaration
    @@ -1411,7 +1527,8 @@
    Parameters
    T[] value - +

    The array of objects to serialize.

    + @@ -1426,7 +1543,8 @@
    Type Parameters
    T - +

    A type that implements INetSerializable and has a parameterless constructor.

    + @@ -1434,7 +1552,8 @@
    Type Parameters

    PutBytesWithLength(byte[])

    -
    +

    Serializes a byte array prefixed with its ushort length.

    +
    Declaration
    @@ -1453,7 +1572,8 @@
    Parameters
    byte[] data - +

    The source array.

    + @@ -1461,7 +1581,8 @@
    Parameters

    PutBytesWithLength(byte[], int, ushort)

    -
    +

    Serializes a segment of a byte array prefixed with its ushort length.

    +
    Declaration
    @@ -1480,17 +1601,67 @@
    Parameters
    byte[] data - +

    The source byte array.

    + int offset - +

    The starting index in the source array.

    + ushort length - +

    The number of bytes to write.

    + + + + + + + +

    PutEnum<T>(T)

    +

    Writes an enum value of type T to the internal data buffer at the current position.
    +Automatically resizes the buffer if LiteNetLib.Utils.NetDataWriter._autoResize is enabled. +Advances the position by the size of T.

    +
    +
    +
    Declaration
    +
    +
    public void PutEnum<T>(T value) where T : unmanaged, Enum
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tvalue

    The enum value to write.

    +
    +
    Type Parameters
    + + + + + + + + + + +
    NameDescription
    T

    An unmanaged enum type to write.

    +
    @@ -1498,7 +1669,8 @@
    Parameters

    PutLargeString(string)

    -
    +

    Serializes a string using a 4-byte int length header.

    +
    Declaration
    @@ -1517,7 +1689,60 @@
    Parameters
    string value - +

    The string to write.

    + + + + +
    Remarks
    +

    Recommended for strings that may exceed the 65535 byte limit of standard ushort length headers.
    +Uses UTF8.

    +
    + + + +

    PutNullableUnmanaged<T>(T?)

    +

    Writes a nullable value of type T into the internal byte buffer at the current position, +first writing a bool indicating whether the value is present, +and then writing the value itself if it exists.
    Advances the position by 1 byte for the presence flag plus +the size of T if the value is present.

    +
    +
    +
    Declaration
    +
    +
    public void PutNullableUnmanaged<T>(T? value) where T : unmanaged
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    T?value

    The nullable value to write into the buffer. If null, only a false flag is written.

    +
    +
    Type Parameters
    + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type to write into the buffer.

    +
    @@ -1525,7 +1750,8 @@
    Parameters

    PutSBytesWithLength(sbyte[])

    -
    +

    Serializes an sbyte array prefixed with its ushort length.

    +
    Declaration
    @@ -1544,7 +1770,8 @@
    Parameters
    sbyte[] data - +

    The source array.

    + @@ -1552,7 +1779,8 @@
    Parameters

    PutSBytesWithLength(sbyte[], int, ushort)

    -
    +

    Serializes a segment of an sbyte array prefixed with its ushort length.

    +
    Declaration
    @@ -1571,17 +1799,159 @@
    Parameters
    sbyte[] data - +

    The source sbyte array.

    + int offset - +

    The starting index in the source array.

    + ushort length - +

    The number of elements to write.

    + + + + + + + +

    PutSpan<T>(Span<T>)

    +

    Serializes a Span<T> of unmanaged values to the internal buffer.

    +
    +
    +
    Declaration
    +
    +
    public void PutSpan<T>(Span<T> span) where T : unmanaged
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Span<T>span

    The span of data to write.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    The unmanaged type of the span elements.

    +
    +
    Remarks
    +

    Writes a 2-byte ushort length header followed by the raw binary data.

    +
    + + + +

    PutUnmanagedArray<T>(T[])

    +

    Serializes an array of unmanaged values.

    +
    +
    +
    Declaration
    +
    +
    public void PutUnmanagedArray<T>(T[] arr) where T : unmanaged
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    T[]arr

    The array to serialize.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    The unmanaged type of the array elements.

    +
    + + + +

    PutUnmanaged<T>(T)

    +

    Writes a value of type T into the internal byte buffer at the current position, +advancing the position by the size of T.

    +
    +
    +
    Declaration
    +
    +
    public void PutUnmanaged<T>(T value) where T : unmanaged
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tvalue

    The value to write into the buffer.

    +
    +
    Type Parameters
    + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type to write into the buffer.

    +
    @@ -1589,7 +1959,8 @@
    Parameters

    Put<T>(T)

    -
    +

    Serializes an object implementing INetSerializable.

    +
    Declaration
    @@ -1608,7 +1979,8 @@
    Parameters
    T obj - +

    The object instance to serialize.

    + @@ -1623,15 +1995,20 @@
    Type Parameters
    T - +

    A type that implements the INetSerializable interface.

    + +
    Remarks
    +

    This method calls the Serialize(NetDataWriter) method on the provided obj.

    +

    Reset()

    -
    +

    Resets the _position to 0, effectively clearing the buffer for reuse.

    +
    Declaration
    @@ -1641,7 +2018,8 @@
    Declaration

    Reset(int)

    -
    +

    Resets the _position to 0 and ensures the internal buffer has at least the specified size.

    +
    Declaration
    @@ -1660,15 +2038,20 @@
    Parameters
    int size - +

    The minimum capacity required for the internal buffer.

    + +
    Remarks
    +

    If the current buffer is smaller than size, ResizeIfNeed(int) will allocate a larger byte array.

    +

    ResizeIfNeed(int)

    -
    +

    Ensures the internal buffer is at least newSize.

    +
    Declaration
    @@ -1687,10 +2070,15 @@
    Parameters
    int newSize - +

    The required minimum size of the buffer.

    + +
    Remarks
    +

    If an allocation is necessary, the buffer grows to either newSize +or doubles its current size, whichever is larger.

    +
    diff --git a/docs/api/LiteNetLib.html b/docs/api/LiteNetLib.html index 72a2a32b..842b779e 100644 --- a/docs/api/LiteNetLib.html +++ b/docs/api/LiteNetLib.html @@ -87,6 +87,8 @@

    EventBasedNetLi

    InvalidPacketException

    +

    LiteConnectionRequest

    +

    LiteNetManager

    Main class for all network operations. Can be used as client and/or server.

    @@ -96,6 +98,8 @@

    LiteNetPeer

    NatPunchModule

    Module for UDP NAT Hole punching operations. Can be accessed from NetManager

    +

    NetConnectRequestPacket

    +

    NetConstants

    Network constants. Can be tuned from sources for your purposes.

    diff --git a/docs/api/toc.html b/docs/api/toc.html index ebd278b0..290589f2 100644 --- a/docs/api/toc.html +++ b/docs/api/toc.html @@ -56,6 +56,9 @@
  • InvalidPacketException
  • +
  • + LiteConnectionRequest +
  • LiteNetManager
  • @@ -74,6 +77,9 @@
  • NatPunchModule
  • +
  • + NetConnectRequestPacket +
  • NetConstants
  • diff --git a/docs/api/toc.json b/docs/api/toc.json index 82dcfb4e..17d2e194 100644 --- a/docs/api/toc.json +++ b/docs/api/toc.json @@ -1,2 +1,2 @@ -{"items":[{"name":"LiteNetLib","href":"LiteNetLib.html","topicHref":"LiteNetLib.html","topicUid":"LiteNetLib","type":"Namespace","items":[{"name":"ConnectionRequest","href":"LiteNetLib.ConnectionRequest.html","topicHref":"LiteNetLib.ConnectionRequest.html","topicUid":"LiteNetLib.ConnectionRequest","type":"Class"},{"name":"ConnectionState","href":"LiteNetLib.ConnectionState.html","topicHref":"LiteNetLib.ConnectionState.html","topicUid":"LiteNetLib.ConnectionState","type":"Enum"},{"name":"DeliveryMethod","href":"LiteNetLib.DeliveryMethod.html","topicHref":"LiteNetLib.DeliveryMethod.html","topicUid":"LiteNetLib.DeliveryMethod","type":"Enum"},{"name":"DisconnectInfo","href":"LiteNetLib.DisconnectInfo.html","topicHref":"LiteNetLib.DisconnectInfo.html","topicUid":"LiteNetLib.DisconnectInfo","type":"Struct"},{"name":"DisconnectReason","href":"LiteNetLib.DisconnectReason.html","topicHref":"LiteNetLib.DisconnectReason.html","topicUid":"LiteNetLib.DisconnectReason","type":"Enum"},{"name":"EventBasedLiteNetListener","href":"LiteNetLib.EventBasedLiteNetListener.html","topicHref":"LiteNetLib.EventBasedLiteNetListener.html","topicUid":"LiteNetLib.EventBasedLiteNetListener","type":"Class"},{"name":"EventBasedNatPunchListener","href":"LiteNetLib.EventBasedNatPunchListener.html","topicHref":"LiteNetLib.EventBasedNatPunchListener.html","topicUid":"LiteNetLib.EventBasedNatPunchListener","type":"Class"},{"name":"EventBasedNetListener","href":"LiteNetLib.EventBasedNetListener.html","topicHref":"LiteNetLib.EventBasedNetListener.html","topicUid":"LiteNetLib.EventBasedNetListener","type":"Class"},{"name":"ILiteNetEventListener","href":"LiteNetLib.ILiteNetEventListener.html","topicHref":"LiteNetLib.ILiteNetEventListener.html","topicUid":"LiteNetLib.ILiteNetEventListener","type":"Interface"},{"name":"INatPunchListener","href":"LiteNetLib.INatPunchListener.html","topicHref":"LiteNetLib.INatPunchListener.html","topicUid":"LiteNetLib.INatPunchListener","type":"Interface"},{"name":"INetEventListener","href":"LiteNetLib.INetEventListener.html","topicHref":"LiteNetLib.INetEventListener.html","topicUid":"LiteNetLib.INetEventListener","type":"Interface"},{"name":"INetLogger","href":"LiteNetLib.INetLogger.html","topicHref":"LiteNetLib.INetLogger.html","topicUid":"LiteNetLib.INetLogger","type":"Interface"},{"name":"InvalidPacketException","href":"LiteNetLib.InvalidPacketException.html","topicHref":"LiteNetLib.InvalidPacketException.html","topicUid":"LiteNetLib.InvalidPacketException","type":"Class"},{"name":"LiteNetManager","href":"LiteNetLib.LiteNetManager.html","topicHref":"LiteNetLib.LiteNetManager.html","topicUid":"LiteNetLib.LiteNetManager","type":"Class"},{"name":"LiteNetManager.NetPeerEnumerator","href":"LiteNetLib.LiteNetManager.NetPeerEnumerator-1.html","topicHref":"LiteNetLib.LiteNetManager.NetPeerEnumerator-1.html","topicUid":"LiteNetLib.LiteNetManager.NetPeerEnumerator`1","type":"Struct"},{"name":"LiteNetPeer","href":"LiteNetLib.LiteNetPeer.html","topicHref":"LiteNetLib.LiteNetPeer.html","topicUid":"LiteNetLib.LiteNetPeer","type":"Class"},{"name":"LocalAddrType","href":"LiteNetLib.LocalAddrType.html","topicHref":"LiteNetLib.LocalAddrType.html","topicUid":"LiteNetLib.LocalAddrType","type":"Enum"},{"name":"NatAddressType","href":"LiteNetLib.NatAddressType.html","topicHref":"LiteNetLib.NatAddressType.html","topicUid":"LiteNetLib.NatAddressType","type":"Enum"},{"name":"NatPunchModule","href":"LiteNetLib.NatPunchModule.html","topicHref":"LiteNetLib.NatPunchModule.html","topicUid":"LiteNetLib.NatPunchModule","type":"Class"},{"name":"NetConstants","href":"LiteNetLib.NetConstants.html","topicHref":"LiteNetLib.NetConstants.html","topicUid":"LiteNetLib.NetConstants","type":"Class"},{"name":"NetDebug","href":"LiteNetLib.NetDebug.html","topicHref":"LiteNetLib.NetDebug.html","topicUid":"LiteNetLib.NetDebug","type":"Class"},{"name":"NetEvent","href":"LiteNetLib.NetEvent.html","topicHref":"LiteNetLib.NetEvent.html","topicUid":"LiteNetLib.NetEvent","type":"Class"},{"name":"NetEvent.EType","href":"LiteNetLib.NetEvent.EType.html","topicHref":"LiteNetLib.NetEvent.EType.html","topicUid":"LiteNetLib.NetEvent.EType","type":"Enum"},{"name":"NetLogLevel","href":"LiteNetLib.NetLogLevel.html","topicHref":"LiteNetLib.NetLogLevel.html","topicUid":"LiteNetLib.NetLogLevel","type":"Enum"},{"name":"NetManager","href":"LiteNetLib.NetManager.html","topicHref":"LiteNetLib.NetManager.html","topicUid":"LiteNetLib.NetManager","type":"Class"},{"name":"NetPacketReader","href":"LiteNetLib.NetPacketReader.html","topicHref":"LiteNetLib.NetPacketReader.html","topicUid":"LiteNetLib.NetPacketReader","type":"Class"},{"name":"NetPeer","href":"LiteNetLib.NetPeer.html","topicHref":"LiteNetLib.NetPeer.html","topicUid":"LiteNetLib.NetPeer","type":"Class"},{"name":"NetStatistics","href":"LiteNetLib.NetStatistics.html","topicHref":"LiteNetLib.NetStatistics.html","topicUid":"LiteNetLib.NetStatistics","type":"Class"},{"name":"NetUtils","href":"LiteNetLib.NetUtils.html","topicHref":"LiteNetLib.NetUtils.html","topicUid":"LiteNetLib.NetUtils","type":"Class"},{"name":"PooledPacket","href":"LiteNetLib.PooledPacket.html","topicHref":"LiteNetLib.PooledPacket.html","topicUid":"LiteNetLib.PooledPacket","type":"Struct"},{"name":"TooBigPacketException","href":"LiteNetLib.TooBigPacketException.html","topicHref":"LiteNetLib.TooBigPacketException.html","topicUid":"LiteNetLib.TooBigPacketException","type":"Class"},{"name":"UnconnectedMessageType","href":"LiteNetLib.UnconnectedMessageType.html","topicHref":"LiteNetLib.UnconnectedMessageType.html","topicUid":"LiteNetLib.UnconnectedMessageType","type":"Enum"}]},{"name":"LiteNetLib.Layers","href":"LiteNetLib.Layers.html","topicHref":"LiteNetLib.Layers.html","topicUid":"LiteNetLib.Layers","type":"Namespace","items":[{"name":"Crc32cLayer","href":"LiteNetLib.Layers.Crc32cLayer.html","topicHref":"LiteNetLib.Layers.Crc32cLayer.html","topicUid":"LiteNetLib.Layers.Crc32cLayer","type":"Class"},{"name":"PacketLayerBase","href":"LiteNetLib.Layers.PacketLayerBase.html","topicHref":"LiteNetLib.Layers.PacketLayerBase.html","topicUid":"LiteNetLib.Layers.PacketLayerBase","type":"Class"},{"name":"XorEncryptLayer","href":"LiteNetLib.Layers.XorEncryptLayer.html","topicHref":"LiteNetLib.Layers.XorEncryptLayer.html","topicUid":"LiteNetLib.Layers.XorEncryptLayer","type":"Class"}]},{"name":"LiteNetLib.Utils","href":"LiteNetLib.Utils.html","topicHref":"LiteNetLib.Utils.html","topicUid":"LiteNetLib.Utils","type":"Namespace","items":[{"name":"CRC32C","href":"LiteNetLib.Utils.CRC32C.html","topicHref":"LiteNetLib.Utils.CRC32C.html","topicUid":"LiteNetLib.Utils.CRC32C","type":"Class"},{"name":"FastBitConverter","href":"LiteNetLib.Utils.FastBitConverter.html","topicHref":"LiteNetLib.Utils.FastBitConverter.html","topicUid":"LiteNetLib.Utils.FastBitConverter","type":"Class"},{"name":"INetSerializable","href":"LiteNetLib.Utils.INetSerializable.html","topicHref":"LiteNetLib.Utils.INetSerializable.html","topicUid":"LiteNetLib.Utils.INetSerializable","type":"Interface"},{"name":"InvalidTypeException","href":"LiteNetLib.Utils.InvalidTypeException.html","topicHref":"LiteNetLib.Utils.InvalidTypeException.html","topicUid":"LiteNetLib.Utils.InvalidTypeException","type":"Class"},{"name":"NetDataReader","href":"LiteNetLib.Utils.NetDataReader.html","topicHref":"LiteNetLib.Utils.NetDataReader.html","topicUid":"LiteNetLib.Utils.NetDataReader","type":"Class"},{"name":"NetDataWriter","href":"LiteNetLib.Utils.NetDataWriter.html","topicHref":"LiteNetLib.Utils.NetDataWriter.html","topicUid":"LiteNetLib.Utils.NetDataWriter","type":"Class"},{"name":"NetPacketProcessor","href":"LiteNetLib.Utils.NetPacketProcessor.html","topicHref":"LiteNetLib.Utils.NetPacketProcessor.html","topicUid":"LiteNetLib.Utils.NetPacketProcessor","type":"Class"},{"name":"NetSerializer","href":"LiteNetLib.Utils.NetSerializer.html","topicHref":"LiteNetLib.Utils.NetSerializer.html","topicUid":"LiteNetLib.Utils.NetSerializer","type":"Class"},{"name":"NtpLeapIndicator","href":"LiteNetLib.Utils.NtpLeapIndicator.html","topicHref":"LiteNetLib.Utils.NtpLeapIndicator.html","topicUid":"LiteNetLib.Utils.NtpLeapIndicator","type":"Enum"},{"name":"NtpMode","href":"LiteNetLib.Utils.NtpMode.html","topicHref":"LiteNetLib.Utils.NtpMode.html","topicUid":"LiteNetLib.Utils.NtpMode","type":"Enum"},{"name":"NtpPacket","href":"LiteNetLib.Utils.NtpPacket.html","topicHref":"LiteNetLib.Utils.NtpPacket.html","topicUid":"LiteNetLib.Utils.NtpPacket","type":"Class"},{"name":"ParseException","href":"LiteNetLib.Utils.ParseException.html","topicHref":"LiteNetLib.Utils.ParseException.html","topicUid":"LiteNetLib.Utils.ParseException","type":"Class"},{"name":"PreserveAttribute","href":"LiteNetLib.Utils.PreserveAttribute.html","topicHref":"LiteNetLib.Utils.PreserveAttribute.html","topicUid":"LiteNetLib.Utils.PreserveAttribute","type":"Class"}]}],"memberLayout":"SamePage"} +{"items":[{"name":"LiteNetLib","href":"LiteNetLib.html","topicHref":"LiteNetLib.html","topicUid":"LiteNetLib","type":"Namespace","items":[{"name":"ConnectionRequest","href":"LiteNetLib.ConnectionRequest.html","topicHref":"LiteNetLib.ConnectionRequest.html","topicUid":"LiteNetLib.ConnectionRequest","type":"Class"},{"name":"ConnectionState","href":"LiteNetLib.ConnectionState.html","topicHref":"LiteNetLib.ConnectionState.html","topicUid":"LiteNetLib.ConnectionState","type":"Enum"},{"name":"DeliveryMethod","href":"LiteNetLib.DeliveryMethod.html","topicHref":"LiteNetLib.DeliveryMethod.html","topicUid":"LiteNetLib.DeliveryMethod","type":"Enum"},{"name":"DisconnectInfo","href":"LiteNetLib.DisconnectInfo.html","topicHref":"LiteNetLib.DisconnectInfo.html","topicUid":"LiteNetLib.DisconnectInfo","type":"Struct"},{"name":"DisconnectReason","href":"LiteNetLib.DisconnectReason.html","topicHref":"LiteNetLib.DisconnectReason.html","topicUid":"LiteNetLib.DisconnectReason","type":"Enum"},{"name":"EventBasedLiteNetListener","href":"LiteNetLib.EventBasedLiteNetListener.html","topicHref":"LiteNetLib.EventBasedLiteNetListener.html","topicUid":"LiteNetLib.EventBasedLiteNetListener","type":"Class"},{"name":"EventBasedNatPunchListener","href":"LiteNetLib.EventBasedNatPunchListener.html","topicHref":"LiteNetLib.EventBasedNatPunchListener.html","topicUid":"LiteNetLib.EventBasedNatPunchListener","type":"Class"},{"name":"EventBasedNetListener","href":"LiteNetLib.EventBasedNetListener.html","topicHref":"LiteNetLib.EventBasedNetListener.html","topicUid":"LiteNetLib.EventBasedNetListener","type":"Class"},{"name":"ILiteNetEventListener","href":"LiteNetLib.ILiteNetEventListener.html","topicHref":"LiteNetLib.ILiteNetEventListener.html","topicUid":"LiteNetLib.ILiteNetEventListener","type":"Interface"},{"name":"INatPunchListener","href":"LiteNetLib.INatPunchListener.html","topicHref":"LiteNetLib.INatPunchListener.html","topicUid":"LiteNetLib.INatPunchListener","type":"Interface"},{"name":"INetEventListener","href":"LiteNetLib.INetEventListener.html","topicHref":"LiteNetLib.INetEventListener.html","topicUid":"LiteNetLib.INetEventListener","type":"Interface"},{"name":"INetLogger","href":"LiteNetLib.INetLogger.html","topicHref":"LiteNetLib.INetLogger.html","topicUid":"LiteNetLib.INetLogger","type":"Interface"},{"name":"InvalidPacketException","href":"LiteNetLib.InvalidPacketException.html","topicHref":"LiteNetLib.InvalidPacketException.html","topicUid":"LiteNetLib.InvalidPacketException","type":"Class"},{"name":"LiteConnectionRequest","href":"LiteNetLib.LiteConnectionRequest.html","topicHref":"LiteNetLib.LiteConnectionRequest.html","topicUid":"LiteNetLib.LiteConnectionRequest","type":"Class"},{"name":"LiteNetManager","href":"LiteNetLib.LiteNetManager.html","topicHref":"LiteNetLib.LiteNetManager.html","topicUid":"LiteNetLib.LiteNetManager","type":"Class"},{"name":"LiteNetManager.NetPeerEnumerator","href":"LiteNetLib.LiteNetManager.NetPeerEnumerator-1.html","topicHref":"LiteNetLib.LiteNetManager.NetPeerEnumerator-1.html","topicUid":"LiteNetLib.LiteNetManager.NetPeerEnumerator`1","type":"Struct"},{"name":"LiteNetPeer","href":"LiteNetLib.LiteNetPeer.html","topicHref":"LiteNetLib.LiteNetPeer.html","topicUid":"LiteNetLib.LiteNetPeer","type":"Class"},{"name":"LocalAddrType","href":"LiteNetLib.LocalAddrType.html","topicHref":"LiteNetLib.LocalAddrType.html","topicUid":"LiteNetLib.LocalAddrType","type":"Enum"},{"name":"NatAddressType","href":"LiteNetLib.NatAddressType.html","topicHref":"LiteNetLib.NatAddressType.html","topicUid":"LiteNetLib.NatAddressType","type":"Enum"},{"name":"NatPunchModule","href":"LiteNetLib.NatPunchModule.html","topicHref":"LiteNetLib.NatPunchModule.html","topicUid":"LiteNetLib.NatPunchModule","type":"Class"},{"name":"NetConnectRequestPacket","href":"LiteNetLib.NetConnectRequestPacket.html","topicHref":"LiteNetLib.NetConnectRequestPacket.html","topicUid":"LiteNetLib.NetConnectRequestPacket","type":"Class"},{"name":"NetConstants","href":"LiteNetLib.NetConstants.html","topicHref":"LiteNetLib.NetConstants.html","topicUid":"LiteNetLib.NetConstants","type":"Class"},{"name":"NetDebug","href":"LiteNetLib.NetDebug.html","topicHref":"LiteNetLib.NetDebug.html","topicUid":"LiteNetLib.NetDebug","type":"Class"},{"name":"NetEvent","href":"LiteNetLib.NetEvent.html","topicHref":"LiteNetLib.NetEvent.html","topicUid":"LiteNetLib.NetEvent","type":"Class"},{"name":"NetEvent.EType","href":"LiteNetLib.NetEvent.EType.html","topicHref":"LiteNetLib.NetEvent.EType.html","topicUid":"LiteNetLib.NetEvent.EType","type":"Enum"},{"name":"NetLogLevel","href":"LiteNetLib.NetLogLevel.html","topicHref":"LiteNetLib.NetLogLevel.html","topicUid":"LiteNetLib.NetLogLevel","type":"Enum"},{"name":"NetManager","href":"LiteNetLib.NetManager.html","topicHref":"LiteNetLib.NetManager.html","topicUid":"LiteNetLib.NetManager","type":"Class"},{"name":"NetPacketReader","href":"LiteNetLib.NetPacketReader.html","topicHref":"LiteNetLib.NetPacketReader.html","topicUid":"LiteNetLib.NetPacketReader","type":"Class"},{"name":"NetPeer","href":"LiteNetLib.NetPeer.html","topicHref":"LiteNetLib.NetPeer.html","topicUid":"LiteNetLib.NetPeer","type":"Class"},{"name":"NetStatistics","href":"LiteNetLib.NetStatistics.html","topicHref":"LiteNetLib.NetStatistics.html","topicUid":"LiteNetLib.NetStatistics","type":"Class"},{"name":"NetUtils","href":"LiteNetLib.NetUtils.html","topicHref":"LiteNetLib.NetUtils.html","topicUid":"LiteNetLib.NetUtils","type":"Class"},{"name":"PooledPacket","href":"LiteNetLib.PooledPacket.html","topicHref":"LiteNetLib.PooledPacket.html","topicUid":"LiteNetLib.PooledPacket","type":"Struct"},{"name":"TooBigPacketException","href":"LiteNetLib.TooBigPacketException.html","topicHref":"LiteNetLib.TooBigPacketException.html","topicUid":"LiteNetLib.TooBigPacketException","type":"Class"},{"name":"UnconnectedMessageType","href":"LiteNetLib.UnconnectedMessageType.html","topicHref":"LiteNetLib.UnconnectedMessageType.html","topicUid":"LiteNetLib.UnconnectedMessageType","type":"Enum"}]},{"name":"LiteNetLib.Layers","href":"LiteNetLib.Layers.html","topicHref":"LiteNetLib.Layers.html","topicUid":"LiteNetLib.Layers","type":"Namespace","items":[{"name":"Crc32cLayer","href":"LiteNetLib.Layers.Crc32cLayer.html","topicHref":"LiteNetLib.Layers.Crc32cLayer.html","topicUid":"LiteNetLib.Layers.Crc32cLayer","type":"Class"},{"name":"PacketLayerBase","href":"LiteNetLib.Layers.PacketLayerBase.html","topicHref":"LiteNetLib.Layers.PacketLayerBase.html","topicUid":"LiteNetLib.Layers.PacketLayerBase","type":"Class"},{"name":"XorEncryptLayer","href":"LiteNetLib.Layers.XorEncryptLayer.html","topicHref":"LiteNetLib.Layers.XorEncryptLayer.html","topicUid":"LiteNetLib.Layers.XorEncryptLayer","type":"Class"}]},{"name":"LiteNetLib.Utils","href":"LiteNetLib.Utils.html","topicHref":"LiteNetLib.Utils.html","topicUid":"LiteNetLib.Utils","type":"Namespace","items":[{"name":"CRC32C","href":"LiteNetLib.Utils.CRC32C.html","topicHref":"LiteNetLib.Utils.CRC32C.html","topicUid":"LiteNetLib.Utils.CRC32C","type":"Class"},{"name":"FastBitConverter","href":"LiteNetLib.Utils.FastBitConverter.html","topicHref":"LiteNetLib.Utils.FastBitConverter.html","topicUid":"LiteNetLib.Utils.FastBitConverter","type":"Class"},{"name":"INetSerializable","href":"LiteNetLib.Utils.INetSerializable.html","topicHref":"LiteNetLib.Utils.INetSerializable.html","topicUid":"LiteNetLib.Utils.INetSerializable","type":"Interface"},{"name":"InvalidTypeException","href":"LiteNetLib.Utils.InvalidTypeException.html","topicHref":"LiteNetLib.Utils.InvalidTypeException.html","topicUid":"LiteNetLib.Utils.InvalidTypeException","type":"Class"},{"name":"NetDataReader","href":"LiteNetLib.Utils.NetDataReader.html","topicHref":"LiteNetLib.Utils.NetDataReader.html","topicUid":"LiteNetLib.Utils.NetDataReader","type":"Class"},{"name":"NetDataWriter","href":"LiteNetLib.Utils.NetDataWriter.html","topicHref":"LiteNetLib.Utils.NetDataWriter.html","topicUid":"LiteNetLib.Utils.NetDataWriter","type":"Class"},{"name":"NetPacketProcessor","href":"LiteNetLib.Utils.NetPacketProcessor.html","topicHref":"LiteNetLib.Utils.NetPacketProcessor.html","topicUid":"LiteNetLib.Utils.NetPacketProcessor","type":"Class"},{"name":"NetSerializer","href":"LiteNetLib.Utils.NetSerializer.html","topicHref":"LiteNetLib.Utils.NetSerializer.html","topicUid":"LiteNetLib.Utils.NetSerializer","type":"Class"},{"name":"NtpLeapIndicator","href":"LiteNetLib.Utils.NtpLeapIndicator.html","topicHref":"LiteNetLib.Utils.NtpLeapIndicator.html","topicUid":"LiteNetLib.Utils.NtpLeapIndicator","type":"Enum"},{"name":"NtpMode","href":"LiteNetLib.Utils.NtpMode.html","topicHref":"LiteNetLib.Utils.NtpMode.html","topicUid":"LiteNetLib.Utils.NtpMode","type":"Enum"},{"name":"NtpPacket","href":"LiteNetLib.Utils.NtpPacket.html","topicHref":"LiteNetLib.Utils.NtpPacket.html","topicUid":"LiteNetLib.Utils.NtpPacket","type":"Class"},{"name":"ParseException","href":"LiteNetLib.Utils.ParseException.html","topicHref":"LiteNetLib.Utils.ParseException.html","topicUid":"LiteNetLib.Utils.ParseException","type":"Class"},{"name":"PreserveAttribute","href":"LiteNetLib.Utils.PreserveAttribute.html","topicHref":"LiteNetLib.Utils.PreserveAttribute.html","topicUid":"LiteNetLib.Utils.PreserveAttribute","type":"Class"}]}],"memberLayout":"SamePage"} diff --git a/docs/manifest.json b/docs/manifest.json index a4b3519d..09864182 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -240,6 +240,20 @@ "Title": "LiteNetLib.Layers", "Summary": null }, + { + "type": "ManagedReference", + "source_relative_path": "api/LiteNetLib.LiteConnectionRequest.yml", + "output": { + ".html": { + "relative_path": "api/LiteNetLib.LiteConnectionRequest.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "LiteNetLib.LiteConnectionRequest", + "Summary": null + }, { "type": "ManagedReference", "source_relative_path": "api/LiteNetLib.LiteNetManager.NetPeerEnumerator-1.yml", @@ -338,6 +352,20 @@ "Title": "LiteNetLib.NatPunchModule", "Summary": "

    Module for UDP NAT Hole punching operations. Can be accessed from NetManager

    \n" }, + { + "type": "ManagedReference", + "source_relative_path": "api/LiteNetLib.NetConnectRequestPacket.yml", + "output": { + ".html": { + "relative_path": "api/LiteNetLib.NetConnectRequestPacket.html" + } + }, + "version": "", + "Uid": null, + "IsMRef": true, + "Title": "LiteNetLib.NetConnectRequestPacket", + "Summary": null + }, { "type": "ManagedReference", "source_relative_path": "api/LiteNetLib.NetConstants.yml", diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index 5968b31b..c0c86392 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -42,108 +42,6 @@ references: isSpec: "True" fullName: LiteNetLib.ConnectionRequest.AcceptIfKey nameWithType: ConnectionRequest.AcceptIfKey -- uid: LiteNetLib.ConnectionRequest.Data - name: Data - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Data - commentId: P:LiteNetLib.ConnectionRequest.Data - fullName: LiteNetLib.ConnectionRequest.Data - nameWithType: ConnectionRequest.Data -- uid: LiteNetLib.ConnectionRequest.Data* - name: Data - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Data_ - commentId: Overload:LiteNetLib.ConnectionRequest.Data - isSpec: "True" - fullName: LiteNetLib.ConnectionRequest.Data - nameWithType: ConnectionRequest.Data -- uid: LiteNetLib.ConnectionRequest.Reject - name: Reject() - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject - commentId: M:LiteNetLib.ConnectionRequest.Reject - fullName: LiteNetLib.ConnectionRequest.Reject() - nameWithType: ConnectionRequest.Reject() -- uid: LiteNetLib.ConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) - name: Reject(NetDataWriter) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject_LiteNetLib_Utils_NetDataWriter_ - commentId: M:LiteNetLib.ConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) - fullName: LiteNetLib.ConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) - nameWithType: ConnectionRequest.Reject(NetDataWriter) -- uid: LiteNetLib.ConnectionRequest.Reject(System.Byte[]) - name: Reject(byte[]) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject_System_Byte___ - commentId: M:LiteNetLib.ConnectionRequest.Reject(System.Byte[]) - name.vb: Reject(Byte()) - fullName: LiteNetLib.ConnectionRequest.Reject(byte[]) - fullName.vb: LiteNetLib.ConnectionRequest.Reject(Byte()) - nameWithType: ConnectionRequest.Reject(byte[]) - nameWithType.vb: ConnectionRequest.Reject(Byte()) -- uid: LiteNetLib.ConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32) - name: Reject(byte[], int, int) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject_System_Byte___System_Int32_System_Int32_ - commentId: M:LiteNetLib.ConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32) - name.vb: Reject(Byte(), Integer, Integer) - fullName: LiteNetLib.ConnectionRequest.Reject(byte[], int, int) - fullName.vb: LiteNetLib.ConnectionRequest.Reject(Byte(), Integer, Integer) - nameWithType: ConnectionRequest.Reject(byte[], int, int) - nameWithType.vb: ConnectionRequest.Reject(Byte(), Integer, Integer) -- uid: LiteNetLib.ConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32,System.Boolean) - name: Reject(byte[], int, int, bool) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject_System_Byte___System_Int32_System_Int32_System_Boolean_ - commentId: M:LiteNetLib.ConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32,System.Boolean) - name.vb: Reject(Byte(), Integer, Integer, Boolean) - fullName: LiteNetLib.ConnectionRequest.Reject(byte[], int, int, bool) - fullName.vb: LiteNetLib.ConnectionRequest.Reject(Byte(), Integer, Integer, Boolean) - nameWithType: ConnectionRequest.Reject(byte[], int, int, bool) - nameWithType.vb: ConnectionRequest.Reject(Byte(), Integer, Integer, Boolean) -- uid: LiteNetLib.ConnectionRequest.Reject* - name: Reject - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_Reject_ - commentId: Overload:LiteNetLib.ConnectionRequest.Reject - isSpec: "True" - fullName: LiteNetLib.ConnectionRequest.Reject - nameWithType: ConnectionRequest.Reject -- uid: LiteNetLib.ConnectionRequest.RejectForce - name: RejectForce() - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RejectForce - commentId: M:LiteNetLib.ConnectionRequest.RejectForce - fullName: LiteNetLib.ConnectionRequest.RejectForce() - nameWithType: ConnectionRequest.RejectForce() -- uid: LiteNetLib.ConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) - name: RejectForce(NetDataWriter) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RejectForce_LiteNetLib_Utils_NetDataWriter_ - commentId: M:LiteNetLib.ConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) - fullName: LiteNetLib.ConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) - nameWithType: ConnectionRequest.RejectForce(NetDataWriter) -- uid: LiteNetLib.ConnectionRequest.RejectForce(System.Byte[]) - name: RejectForce(byte[]) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RejectForce_System_Byte___ - commentId: M:LiteNetLib.ConnectionRequest.RejectForce(System.Byte[]) - name.vb: RejectForce(Byte()) - fullName: LiteNetLib.ConnectionRequest.RejectForce(byte[]) - fullName.vb: LiteNetLib.ConnectionRequest.RejectForce(Byte()) - nameWithType: ConnectionRequest.RejectForce(byte[]) - nameWithType.vb: ConnectionRequest.RejectForce(Byte()) -- uid: LiteNetLib.ConnectionRequest.RejectForce(System.Byte[],System.Int32,System.Int32) - name: RejectForce(byte[], int, int) - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RejectForce_System_Byte___System_Int32_System_Int32_ - commentId: M:LiteNetLib.ConnectionRequest.RejectForce(System.Byte[],System.Int32,System.Int32) - name.vb: RejectForce(Byte(), Integer, Integer) - fullName: LiteNetLib.ConnectionRequest.RejectForce(byte[], int, int) - fullName.vb: LiteNetLib.ConnectionRequest.RejectForce(Byte(), Integer, Integer) - nameWithType: ConnectionRequest.RejectForce(byte[], int, int) - nameWithType.vb: ConnectionRequest.RejectForce(Byte(), Integer, Integer) -- uid: LiteNetLib.ConnectionRequest.RejectForce* - name: RejectForce - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RejectForce_ - commentId: Overload:LiteNetLib.ConnectionRequest.RejectForce - isSpec: "True" - fullName: LiteNetLib.ConnectionRequest.RejectForce - nameWithType: ConnectionRequest.RejectForce -- uid: LiteNetLib.ConnectionRequest.RemoteEndPoint - name: RemoteEndPoint - href: api/LiteNetLib.ConnectionRequest.html#LiteNetLib_ConnectionRequest_RemoteEndPoint - commentId: F:LiteNetLib.ConnectionRequest.RemoteEndPoint - fullName: LiteNetLib.ConnectionRequest.RemoteEndPoint - nameWithType: ConnectionRequest.RemoteEndPoint - uid: LiteNetLib.ConnectionState name: ConnectionState href: api/LiteNetLib.ConnectionState.html @@ -721,12 +619,12 @@ references: commentId: T:LiteNetLib.ILiteNetEventListener fullName: LiteNetLib.ILiteNetEventListener nameWithType: ILiteNetEventListener -- uid: LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.ConnectionRequest) - name: OnConnectionRequest(ConnectionRequest) - href: api/LiteNetLib.ILiteNetEventListener.html#LiteNetLib_ILiteNetEventListener_OnConnectionRequest_LiteNetLib_ConnectionRequest_ - commentId: M:LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.ConnectionRequest) - fullName: LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.ConnectionRequest) - nameWithType: ILiteNetEventListener.OnConnectionRequest(ConnectionRequest) +- uid: LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.LiteConnectionRequest) + name: OnConnectionRequest(LiteConnectionRequest) + href: api/LiteNetLib.ILiteNetEventListener.html#LiteNetLib_ILiteNetEventListener_OnConnectionRequest_LiteNetLib_LiteConnectionRequest_ + commentId: M:LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.LiteConnectionRequest) + fullName: LiteNetLib.ILiteNetEventListener.OnConnectionRequest(LiteNetLib.LiteConnectionRequest) + nameWithType: ILiteNetEventListener.OnConnectionRequest(LiteConnectionRequest) - uid: LiteNetLib.ILiteNetEventListener.OnConnectionRequest* name: OnConnectionRequest href: api/LiteNetLib.ILiteNetEventListener.html#LiteNetLib_ILiteNetEventListener_OnConnectionRequest_ @@ -1300,6 +1198,143 @@ references: isSpec: "True" fullName: LiteNetLib.Layers.XorEncryptLayer.SetKey nameWithType: XorEncryptLayer.SetKey +- uid: LiteNetLib.LiteConnectionRequest + name: LiteConnectionRequest + href: api/LiteNetLib.LiteConnectionRequest.html + commentId: T:LiteNetLib.LiteConnectionRequest + fullName: LiteNetLib.LiteConnectionRequest + nameWithType: LiteConnectionRequest +- uid: LiteNetLib.LiteConnectionRequest.Accept + name: Accept() + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Accept + commentId: M:LiteNetLib.LiteConnectionRequest.Accept + fullName: LiteNetLib.LiteConnectionRequest.Accept() + nameWithType: LiteConnectionRequest.Accept() +- uid: LiteNetLib.LiteConnectionRequest.Accept* + name: Accept + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Accept_ + commentId: Overload:LiteNetLib.LiteConnectionRequest.Accept + isSpec: "True" + fullName: LiteNetLib.LiteConnectionRequest.Accept + nameWithType: LiteConnectionRequest.Accept +- uid: LiteNetLib.LiteConnectionRequest.AcceptIfKey(System.String) + name: AcceptIfKey(string) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_AcceptIfKey_System_String_ + commentId: M:LiteNetLib.LiteConnectionRequest.AcceptIfKey(System.String) + name.vb: AcceptIfKey(String) + fullName: LiteNetLib.LiteConnectionRequest.AcceptIfKey(string) + fullName.vb: LiteNetLib.LiteConnectionRequest.AcceptIfKey(String) + nameWithType: LiteConnectionRequest.AcceptIfKey(string) + nameWithType.vb: LiteConnectionRequest.AcceptIfKey(String) +- uid: LiteNetLib.LiteConnectionRequest.AcceptIfKey* + name: AcceptIfKey + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_AcceptIfKey_ + commentId: Overload:LiteNetLib.LiteConnectionRequest.AcceptIfKey + isSpec: "True" + fullName: LiteNetLib.LiteConnectionRequest.AcceptIfKey + nameWithType: LiteConnectionRequest.AcceptIfKey +- uid: LiteNetLib.LiteConnectionRequest.Data + name: Data + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Data + commentId: P:LiteNetLib.LiteConnectionRequest.Data + fullName: LiteNetLib.LiteConnectionRequest.Data + nameWithType: LiteConnectionRequest.Data +- uid: LiteNetLib.LiteConnectionRequest.Data* + name: Data + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Data_ + commentId: Overload:LiteNetLib.LiteConnectionRequest.Data + isSpec: "True" + fullName: LiteNetLib.LiteConnectionRequest.Data + nameWithType: LiteConnectionRequest.Data +- uid: LiteNetLib.LiteConnectionRequest.Reject + name: Reject() + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject + commentId: M:LiteNetLib.LiteConnectionRequest.Reject + fullName: LiteNetLib.LiteConnectionRequest.Reject() + nameWithType: LiteConnectionRequest.Reject() +- uid: LiteNetLib.LiteConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) + name: Reject(NetDataWriter) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject_LiteNetLib_Utils_NetDataWriter_ + commentId: M:LiteNetLib.LiteConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) + fullName: LiteNetLib.LiteConnectionRequest.Reject(LiteNetLib.Utils.NetDataWriter) + nameWithType: LiteConnectionRequest.Reject(NetDataWriter) +- uid: LiteNetLib.LiteConnectionRequest.Reject(System.Byte[]) + name: Reject(byte[]) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject_System_Byte___ + commentId: M:LiteNetLib.LiteConnectionRequest.Reject(System.Byte[]) + name.vb: Reject(Byte()) + fullName: LiteNetLib.LiteConnectionRequest.Reject(byte[]) + fullName.vb: LiteNetLib.LiteConnectionRequest.Reject(Byte()) + nameWithType: LiteConnectionRequest.Reject(byte[]) + nameWithType.vb: LiteConnectionRequest.Reject(Byte()) +- uid: LiteNetLib.LiteConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32) + name: Reject(byte[], int, int) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject_System_Byte___System_Int32_System_Int32_ + commentId: M:LiteNetLib.LiteConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32) + name.vb: Reject(Byte(), Integer, Integer) + fullName: LiteNetLib.LiteConnectionRequest.Reject(byte[], int, int) + fullName.vb: LiteNetLib.LiteConnectionRequest.Reject(Byte(), Integer, Integer) + nameWithType: LiteConnectionRequest.Reject(byte[], int, int) + nameWithType.vb: LiteConnectionRequest.Reject(Byte(), Integer, Integer) +- uid: LiteNetLib.LiteConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32,System.Boolean) + name: Reject(byte[], int, int, bool) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject_System_Byte___System_Int32_System_Int32_System_Boolean_ + commentId: M:LiteNetLib.LiteConnectionRequest.Reject(System.Byte[],System.Int32,System.Int32,System.Boolean) + name.vb: Reject(Byte(), Integer, Integer, Boolean) + fullName: LiteNetLib.LiteConnectionRequest.Reject(byte[], int, int, bool) + fullName.vb: LiteNetLib.LiteConnectionRequest.Reject(Byte(), Integer, Integer, Boolean) + nameWithType: LiteConnectionRequest.Reject(byte[], int, int, bool) + nameWithType.vb: LiteConnectionRequest.Reject(Byte(), Integer, Integer, Boolean) +- uid: LiteNetLib.LiteConnectionRequest.Reject* + name: Reject + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_Reject_ + commentId: Overload:LiteNetLib.LiteConnectionRequest.Reject + isSpec: "True" + fullName: LiteNetLib.LiteConnectionRequest.Reject + nameWithType: LiteConnectionRequest.Reject +- uid: LiteNetLib.LiteConnectionRequest.RejectForce + name: RejectForce() + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RejectForce + commentId: M:LiteNetLib.LiteConnectionRequest.RejectForce + fullName: LiteNetLib.LiteConnectionRequest.RejectForce() + nameWithType: LiteConnectionRequest.RejectForce() +- uid: LiteNetLib.LiteConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) + name: RejectForce(NetDataWriter) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RejectForce_LiteNetLib_Utils_NetDataWriter_ + commentId: M:LiteNetLib.LiteConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) + fullName: LiteNetLib.LiteConnectionRequest.RejectForce(LiteNetLib.Utils.NetDataWriter) + nameWithType: LiteConnectionRequest.RejectForce(NetDataWriter) +- uid: LiteNetLib.LiteConnectionRequest.RejectForce(System.Byte[]) + name: RejectForce(byte[]) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RejectForce_System_Byte___ + commentId: M:LiteNetLib.LiteConnectionRequest.RejectForce(System.Byte[]) + name.vb: RejectForce(Byte()) + fullName: LiteNetLib.LiteConnectionRequest.RejectForce(byte[]) + fullName.vb: LiteNetLib.LiteConnectionRequest.RejectForce(Byte()) + nameWithType: LiteConnectionRequest.RejectForce(byte[]) + nameWithType.vb: LiteConnectionRequest.RejectForce(Byte()) +- uid: LiteNetLib.LiteConnectionRequest.RejectForce(System.Byte[],System.Int32,System.Int32) + name: RejectForce(byte[], int, int) + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RejectForce_System_Byte___System_Int32_System_Int32_ + commentId: M:LiteNetLib.LiteConnectionRequest.RejectForce(System.Byte[],System.Int32,System.Int32) + name.vb: RejectForce(Byte(), Integer, Integer) + fullName: LiteNetLib.LiteConnectionRequest.RejectForce(byte[], int, int) + fullName.vb: LiteNetLib.LiteConnectionRequest.RejectForce(Byte(), Integer, Integer) + nameWithType: LiteConnectionRequest.RejectForce(byte[], int, int) + nameWithType.vb: LiteConnectionRequest.RejectForce(Byte(), Integer, Integer) +- uid: LiteNetLib.LiteConnectionRequest.RejectForce* + name: RejectForce + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RejectForce_ + commentId: Overload:LiteNetLib.LiteConnectionRequest.RejectForce + isSpec: "True" + fullName: LiteNetLib.LiteConnectionRequest.RejectForce + nameWithType: LiteConnectionRequest.RejectForce +- uid: LiteNetLib.LiteConnectionRequest.RemoteEndPoint + name: RemoteEndPoint + href: api/LiteNetLib.LiteConnectionRequest.html#LiteNetLib_LiteConnectionRequest_RemoteEndPoint + commentId: F:LiteNetLib.LiteConnectionRequest.RemoteEndPoint + fullName: LiteNetLib.LiteConnectionRequest.RemoteEndPoint + nameWithType: LiteConnectionRequest.RemoteEndPoint - uid: LiteNetLib.LiteNetManager name: LiteNetManager href: api/LiteNetLib.LiteNetManager.html @@ -1431,15 +1466,28 @@ references: isSpec: "True" fullName: LiteNetLib.LiteNetManager.ContainsPeer nameWithType: LiteNetManager.ContainsPeer -- uid: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest,System.Int32) - name: CreateIncomingPeer(ConnectionRequest, int) - href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_CreateIncomingPeer_LiteNetLib_ConnectionRequest_System_Int32_ - commentId: M:LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest,System.Int32) - name.vb: CreateIncomingPeer(ConnectionRequest, Integer) - fullName: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest, int) - fullName.vb: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest, Integer) - nameWithType: LiteNetManager.CreateIncomingPeer(ConnectionRequest, int) - nameWithType.vb: LiteNetManager.CreateIncomingPeer(ConnectionRequest, Integer) +- uid: LiteNetLib.LiteNetManager.CreateConnectionRequest(System.Net.IPEndPoint,LiteNetLib.NetConnectRequestPacket) + name: CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket) + href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_CreateConnectionRequest_System_Net_IPEndPoint_LiteNetLib_NetConnectRequestPacket_ + commentId: M:LiteNetLib.LiteNetManager.CreateConnectionRequest(System.Net.IPEndPoint,LiteNetLib.NetConnectRequestPacket) + fullName: LiteNetLib.LiteNetManager.CreateConnectionRequest(System.Net.IPEndPoint, LiteNetLib.NetConnectRequestPacket) + nameWithType: LiteNetManager.CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket) +- uid: LiteNetLib.LiteNetManager.CreateConnectionRequest* + name: CreateConnectionRequest + href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_CreateConnectionRequest_ + commentId: Overload:LiteNetLib.LiteNetManager.CreateConnectionRequest + isSpec: "True" + fullName: LiteNetLib.LiteNetManager.CreateConnectionRequest + nameWithType: LiteNetManager.CreateConnectionRequest +- uid: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest,System.Int32) + name: CreateIncomingPeer(LiteConnectionRequest, int) + href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_CreateIncomingPeer_LiteNetLib_LiteConnectionRequest_System_Int32_ + commentId: M:LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest,System.Int32) + name.vb: CreateIncomingPeer(LiteConnectionRequest, Integer) + fullName: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest, int) + fullName.vb: LiteNetLib.LiteNetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest, Integer) + nameWithType: LiteNetManager.CreateIncomingPeer(LiteConnectionRequest, int) + nameWithType.vb: LiteNetManager.CreateIncomingPeer(LiteConnectionRequest, Integer) - uid: LiteNetLib.LiteNetManager.CreateIncomingPeer* name: CreateIncomingPeer href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_CreateIncomingPeer_ @@ -2955,6 +3003,48 @@ references: commentId: F:LiteNetLib.NatPunchModule.UnsyncedEvents fullName: LiteNetLib.NatPunchModule.UnsyncedEvents nameWithType: NatPunchModule.UnsyncedEvents +- uid: LiteNetLib.NetConnectRequestPacket + name: NetConnectRequestPacket + href: api/LiteNetLib.NetConnectRequestPacket.html + commentId: T:LiteNetLib.NetConnectRequestPacket + fullName: LiteNetLib.NetConnectRequestPacket + nameWithType: NetConnectRequestPacket +- uid: LiteNetLib.NetConnectRequestPacket.ConnectionNumber + name: ConnectionNumber + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_ConnectionNumber + commentId: F:LiteNetLib.NetConnectRequestPacket.ConnectionNumber + fullName: LiteNetLib.NetConnectRequestPacket.ConnectionNumber + nameWithType: NetConnectRequestPacket.ConnectionNumber +- uid: LiteNetLib.NetConnectRequestPacket.ConnectionTime + name: ConnectionTime + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_ConnectionTime + commentId: F:LiteNetLib.NetConnectRequestPacket.ConnectionTime + fullName: LiteNetLib.NetConnectRequestPacket.ConnectionTime + nameWithType: NetConnectRequestPacket.ConnectionTime +- uid: LiteNetLib.NetConnectRequestPacket.Data + name: Data + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_Data + commentId: F:LiteNetLib.NetConnectRequestPacket.Data + fullName: LiteNetLib.NetConnectRequestPacket.Data + nameWithType: NetConnectRequestPacket.Data +- uid: LiteNetLib.NetConnectRequestPacket.HeaderSize + name: HeaderSize + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_HeaderSize + commentId: F:LiteNetLib.NetConnectRequestPacket.HeaderSize + fullName: LiteNetLib.NetConnectRequestPacket.HeaderSize + nameWithType: NetConnectRequestPacket.HeaderSize +- uid: LiteNetLib.NetConnectRequestPacket.PeerId + name: PeerId + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_PeerId + commentId: F:LiteNetLib.NetConnectRequestPacket.PeerId + fullName: LiteNetLib.NetConnectRequestPacket.PeerId + nameWithType: NetConnectRequestPacket.PeerId +- uid: LiteNetLib.NetConnectRequestPacket.TargetAddress + name: TargetAddress + href: api/LiteNetLib.NetConnectRequestPacket.html#LiteNetLib_NetConnectRequestPacket_TargetAddress + commentId: F:LiteNetLib.NetConnectRequestPacket.TargetAddress + fullName: LiteNetLib.NetConnectRequestPacket.TargetAddress + nameWithType: NetConnectRequestPacket.TargetAddress - uid: LiteNetLib.NetConstants name: NetConstants href: api/LiteNetLib.NetConstants.html @@ -3331,15 +3421,28 @@ references: isSpec: "True" fullName: LiteNetLib.NetManager.Connect nameWithType: NetManager.Connect -- uid: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest,System.Int32) - name: CreateIncomingPeer(ConnectionRequest, int) - href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_CreateIncomingPeer_LiteNetLib_ConnectionRequest_System_Int32_ - commentId: M:LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest,System.Int32) - name.vb: CreateIncomingPeer(ConnectionRequest, Integer) - fullName: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest, int) - fullName.vb: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.ConnectionRequest, Integer) - nameWithType: NetManager.CreateIncomingPeer(ConnectionRequest, int) - nameWithType.vb: NetManager.CreateIncomingPeer(ConnectionRequest, Integer) +- uid: LiteNetLib.NetManager.CreateConnectionRequest(System.Net.IPEndPoint,LiteNetLib.NetConnectRequestPacket) + name: CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket) + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_CreateConnectionRequest_System_Net_IPEndPoint_LiteNetLib_NetConnectRequestPacket_ + commentId: M:LiteNetLib.NetManager.CreateConnectionRequest(System.Net.IPEndPoint,LiteNetLib.NetConnectRequestPacket) + fullName: LiteNetLib.NetManager.CreateConnectionRequest(System.Net.IPEndPoint, LiteNetLib.NetConnectRequestPacket) + nameWithType: NetManager.CreateConnectionRequest(IPEndPoint, NetConnectRequestPacket) +- uid: LiteNetLib.NetManager.CreateConnectionRequest* + name: CreateConnectionRequest + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_CreateConnectionRequest_ + commentId: Overload:LiteNetLib.NetManager.CreateConnectionRequest + isSpec: "True" + fullName: LiteNetLib.NetManager.CreateConnectionRequest + nameWithType: NetManager.CreateConnectionRequest +- uid: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest,System.Int32) + name: CreateIncomingPeer(LiteConnectionRequest, int) + href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_CreateIncomingPeer_LiteNetLib_LiteConnectionRequest_System_Int32_ + commentId: M:LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest,System.Int32) + name.vb: CreateIncomingPeer(LiteConnectionRequest, Integer) + fullName: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest, int) + fullName.vb: LiteNetLib.NetManager.CreateIncomingPeer(LiteNetLib.LiteConnectionRequest, Integer) + nameWithType: NetManager.CreateIncomingPeer(LiteConnectionRequest, int) + nameWithType.vb: NetManager.CreateIncomingPeer(LiteConnectionRequest, Integer) - uid: LiteNetLib.NetManager.CreateIncomingPeer* name: CreateIncomingPeer href: api/LiteNetLib.NetManager.html#LiteNetLib_NetManager_CreateIncomingPeer_ @@ -4601,6 +4704,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.GetDoubleArray nameWithType: NetDataReader.GetDoubleArray +- uid: LiteNetLib.Utils.NetDataReader.GetEnum* + name: GetEnum + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetEnum_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.GetEnum + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.GetEnum + nameWithType: NetDataReader.GetEnum +- uid: LiteNetLib.Utils.NetDataReader.GetEnum``1 + name: GetEnum() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetEnum__1 + commentId: M:LiteNetLib.Utils.NetDataReader.GetEnum``1 + name.vb: GetEnum(Of T)() + fullName: LiteNetLib.Utils.NetDataReader.GetEnum() + fullName.vb: LiteNetLib.Utils.NetDataReader.GetEnum(Of T)() + nameWithType: NetDataReader.GetEnum() + nameWithType.vb: NetDataReader.GetEnum(Of T)() - uid: LiteNetLib.Utils.NetDataReader.GetFloat name: GetFloat() href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetFloat @@ -4718,6 +4837,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.GetLongArray nameWithType: NetDataReader.GetLongArray +- uid: LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged* + name: GetNullableUnmanaged + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetNullableUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged + nameWithType: NetDataReader.GetNullableUnmanaged +- uid: LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged``1 + name: GetNullableUnmanaged() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetNullableUnmanaged__1 + commentId: M:LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged``1 + name.vb: GetNullableUnmanaged(Of T)() + fullName: LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged() + fullName.vb: LiteNetLib.Utils.NetDataReader.GetNullableUnmanaged(Of T)() + nameWithType: NetDataReader.GetNullableUnmanaged() + nameWithType.vb: NetDataReader.GetNullableUnmanaged(Of T)() - uid: LiteNetLib.Utils.NetDataReader.GetRemainingBytes name: GetRemainingBytes() href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetRemainingBytes @@ -4944,6 +5079,38 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.GetUShortArray nameWithType: NetDataReader.GetUShortArray +- uid: LiteNetLib.Utils.NetDataReader.GetUnmanaged* + name: GetUnmanaged + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.GetUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.GetUnmanaged + nameWithType: NetDataReader.GetUnmanaged +- uid: LiteNetLib.Utils.NetDataReader.GetUnmanagedArray* + name: GetUnmanagedArray + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetUnmanagedArray_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.GetUnmanagedArray + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.GetUnmanagedArray + nameWithType: NetDataReader.GetUnmanagedArray +- uid: LiteNetLib.Utils.NetDataReader.GetUnmanagedArray``1 + name: GetUnmanagedArray() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetUnmanagedArray__1 + commentId: M:LiteNetLib.Utils.NetDataReader.GetUnmanagedArray``1 + name.vb: GetUnmanagedArray(Of T)() + fullName: LiteNetLib.Utils.NetDataReader.GetUnmanagedArray() + fullName.vb: LiteNetLib.Utils.NetDataReader.GetUnmanagedArray(Of T)() + nameWithType: NetDataReader.GetUnmanagedArray() + nameWithType.vb: NetDataReader.GetUnmanagedArray(Of T)() +- uid: LiteNetLib.Utils.NetDataReader.GetUnmanaged``1 + name: GetUnmanaged() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_GetUnmanaged__1 + commentId: M:LiteNetLib.Utils.NetDataReader.GetUnmanaged``1 + name.vb: GetUnmanaged(Of T)() + fullName: LiteNetLib.Utils.NetDataReader.GetUnmanaged() + fullName.vb: LiteNetLib.Utils.NetDataReader.GetUnmanaged(Of T)() + nameWithType: NetDataReader.GetUnmanaged() + nameWithType.vb: NetDataReader.GetUnmanaged(Of T)() - uid: LiteNetLib.Utils.NetDataReader.Get``1 name: Get() href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Get__1 @@ -5171,6 +5338,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.PeekUShort nameWithType: NetDataReader.PeekUShort +- uid: LiteNetLib.Utils.NetDataReader.PeekUnmanaged* + name: PeekUnmanaged + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.PeekUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.PeekUnmanaged + nameWithType: NetDataReader.PeekUnmanaged +- uid: LiteNetLib.Utils.NetDataReader.PeekUnmanaged``1 + name: PeekUnmanaged() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekUnmanaged__1 + commentId: M:LiteNetLib.Utils.NetDataReader.PeekUnmanaged``1 + name.vb: PeekUnmanaged(Of T)() + fullName: LiteNetLib.Utils.NetDataReader.PeekUnmanaged() + fullName.vb: LiteNetLib.Utils.NetDataReader.PeekUnmanaged(Of T)() + nameWithType: NetDataReader.PeekUnmanaged() + nameWithType.vb: NetDataReader.PeekUnmanaged(Of T)() - uid: LiteNetLib.Utils.NetDataReader.Position name: Position href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_Position @@ -6049,6 +6232,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataWriter.PutBytesWithLength nameWithType: NetDataWriter.PutBytesWithLength +- uid: LiteNetLib.Utils.NetDataWriter.PutEnum* + name: PutEnum + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutEnum_ + commentId: Overload:LiteNetLib.Utils.NetDataWriter.PutEnum + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataWriter.PutEnum + nameWithType: NetDataWriter.PutEnum +- uid: LiteNetLib.Utils.NetDataWriter.PutEnum``1(``0) + name: PutEnum(T) + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutEnum__1___0_ + commentId: M:LiteNetLib.Utils.NetDataWriter.PutEnum``1(``0) + name.vb: PutEnum(Of T)(T) + fullName: LiteNetLib.Utils.NetDataWriter.PutEnum(T) + fullName.vb: LiteNetLib.Utils.NetDataWriter.PutEnum(Of T)(T) + nameWithType: NetDataWriter.PutEnum(T) + nameWithType.vb: NetDataWriter.PutEnum(Of T)(T) - uid: LiteNetLib.Utils.NetDataWriter.PutLargeString(System.String) name: PutLargeString(string) href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutLargeString_System_String_ @@ -6065,6 +6264,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataWriter.PutLargeString nameWithType: NetDataWriter.PutLargeString +- uid: LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged* + name: PutNullableUnmanaged + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutNullableUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged + nameWithType: NetDataWriter.PutNullableUnmanaged +- uid: LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged``1(System.Nullable{``0}) + name: PutNullableUnmanaged(T?) + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutNullableUnmanaged__1_System_Nullable___0__ + commentId: M:LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged``1(System.Nullable{``0}) + name.vb: PutNullableUnmanaged(Of T)(T?) + fullName: LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged(T?) + fullName.vb: LiteNetLib.Utils.NetDataWriter.PutNullableUnmanaged(Of T)(T?) + nameWithType: NetDataWriter.PutNullableUnmanaged(T?) + nameWithType.vb: NetDataWriter.PutNullableUnmanaged(Of T)(T?) - uid: LiteNetLib.Utils.NetDataWriter.PutSBytesWithLength(System.SByte[]) name: PutSBytesWithLength(sbyte[]) href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutSBytesWithLength_System_SByte___ @@ -6090,6 +6305,54 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataWriter.PutSBytesWithLength nameWithType: NetDataWriter.PutSBytesWithLength +- uid: LiteNetLib.Utils.NetDataWriter.PutSpan* + name: PutSpan + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutSpan_ + commentId: Overload:LiteNetLib.Utils.NetDataWriter.PutSpan + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataWriter.PutSpan + nameWithType: NetDataWriter.PutSpan +- uid: LiteNetLib.Utils.NetDataWriter.PutSpan``1(System.Span{``0}) + name: PutSpan(Span) + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutSpan__1_System_Span___0__ + commentId: M:LiteNetLib.Utils.NetDataWriter.PutSpan``1(System.Span{``0}) + name.vb: PutSpan(Of T)(Span(Of T)) + fullName: LiteNetLib.Utils.NetDataWriter.PutSpan(System.Span) + fullName.vb: LiteNetLib.Utils.NetDataWriter.PutSpan(Of T)(System.Span(Of T)) + nameWithType: NetDataWriter.PutSpan(Span) + nameWithType.vb: NetDataWriter.PutSpan(Of T)(Span(Of T)) +- uid: LiteNetLib.Utils.NetDataWriter.PutUnmanaged* + name: PutUnmanaged + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataWriter.PutUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataWriter.PutUnmanaged + nameWithType: NetDataWriter.PutUnmanaged +- uid: LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray* + name: PutUnmanagedArray + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutUnmanagedArray_ + commentId: Overload:LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray + nameWithType: NetDataWriter.PutUnmanagedArray +- uid: LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray``1(``0[]) + name: PutUnmanagedArray(T[]) + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutUnmanagedArray__1___0___ + commentId: M:LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray``1(``0[]) + name.vb: PutUnmanagedArray(Of T)(T()) + fullName: LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray(T[]) + fullName.vb: LiteNetLib.Utils.NetDataWriter.PutUnmanagedArray(Of T)(T()) + nameWithType: NetDataWriter.PutUnmanagedArray(T[]) + nameWithType.vb: NetDataWriter.PutUnmanagedArray(Of T)(T()) +- uid: LiteNetLib.Utils.NetDataWriter.PutUnmanaged``1(``0) + name: PutUnmanaged(T) + href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_PutUnmanaged__1___0_ + commentId: M:LiteNetLib.Utils.NetDataWriter.PutUnmanaged``1(``0) + name.vb: PutUnmanaged(Of T)(T) + fullName: LiteNetLib.Utils.NetDataWriter.PutUnmanaged(T) + fullName.vb: LiteNetLib.Utils.NetDataWriter.PutUnmanaged(Of T)(T) + nameWithType: NetDataWriter.PutUnmanaged(T) + nameWithType.vb: NetDataWriter.PutUnmanaged(Of T)(T) - uid: LiteNetLib.Utils.NetDataWriter.Put``1(``0) name: Put(T) href: api/LiteNetLib.Utils.NetDataWriter.html#LiteNetLib_Utils_NetDataWriter_Put__1___0_ From 982517e4516377cc87276f0c2780eb32f98a275d Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Sun, 22 Mar 2026 13:27:31 +0200 Subject: [PATCH 132/200] Disable push trigger for NuGet publish workflow Removed automatic push trigger for master branch. --- .github/workflows/nuget-publish.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index afe7e34b..a963bc33 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -1,8 +1,6 @@ name: Publish NuGet Package on: - push: - branches: [ master ] workflow_dispatch: jobs: From bf93dc473453c8b2f81fd8c5736ed5548f71ef66 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Sun, 22 Mar 2026 17:46:47 +0200 Subject: [PATCH 133/200] set position to _dataSize in all GetRemainingBytes methods --- LiteNetLib/Utils/NetDataReader.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index fcf3ee04..114dd25f 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -558,16 +558,24 @@ public T Get(Func constructor) where T : class, INetSerializable /// /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetRemainingBytesSpan() => - new ReadOnlySpan(_data, _position, _dataSize - _position); + public ReadOnlySpan GetRemainingBytesSpan() + { + var result = new ReadOnlySpan(_data, _position, _dataSize - _position); + _position = _dataSize; + return result; + } /// /// Returns a of s containing all remaining data. /// /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory GetRemainingBytesMemory() => - new ReadOnlyMemory(_data, _position, _dataSize - _position); + public ReadOnlyMemory GetRemainingBytesMemory() + { + var result = new ReadOnlyMemory(_data, _position, _dataSize - _position); + _position = _dataSize; + return result; + } /// /// Reads all remaining s and returns them as a new array. @@ -578,8 +586,9 @@ public ReadOnlyMemory GetRemainingBytesMemory() => /// public byte[] GetRemainingBytes() { - byte[] outgoingData = new byte[AvailableBytes]; - Buffer.BlockCopy(_data, _position, outgoingData, 0, AvailableBytes); + int size = _dataSize - _position; + byte[] outgoingData = new byte[size]; + Buffer.BlockCopy(_data, _position, outgoingData, 0, size); _position = _dataSize; return outgoingData; } From 8d69673f5e1635db88cbf0f0cd1003e5ce6d8249 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 22 Mar 2026 20:57:37 +0100 Subject: [PATCH 134/200] Fix compile error --- LiteNetLib/Utils/NetDataReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 114dd25f..a93114fa 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -778,7 +778,7 @@ public string PeekString() /// An unmanaged value type. /// The value read from the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public T PeekUnmanaged() where T : unmanaged + public unsafe T PeekUnmanaged() where T : unmanaged { #if NET8_0_OR_GREATER return Unsafe.ReadUnaligned(ref _data[_position]); From a3e78276d6d377df7e5a1e1eeef435ba16abc0fa Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Sun, 22 Mar 2026 20:58:37 +0100 Subject: [PATCH 135/200] Remove allocations from Put IPEndPoint --- LiteNetLib/Utils/NetDataWriter.cs | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 5c00a6e4..18a9fc6a 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -511,20 +511,35 @@ public void PutArray(string[] value, int strMaxLength) /// public void Put(IPEndPoint endPoint) { + int addressSize; + byte familyFlag; + if (endPoint.AddressFamily == AddressFamily.InterNetwork) { - Put((byte)0); + addressSize = 4; + familyFlag = 0; } else if (endPoint.AddressFamily == AddressFamily.InterNetworkV6) { - Put((byte)1); + addressSize = 16; + familyFlag = 1; } else { - throw new ArgumentException("Unsupported address family: " + endPoint.AddressFamily); + throw new ArgumentException($"Unsupported address family: {endPoint.AddressFamily}"); } - Put(endPoint.Address.GetAddressBytes()); + if (_autoResize) + ResizeIfNeed(_position + 1 + addressSize + 2); + + _data[_position++] = familyFlag; + + Span destination = _data.AsSpan(_position, addressSize); + if (!endPoint.Address.TryWriteBytes(destination, out int written)) + throw new ArgumentException("Failed to write IP bytes."); + + _position += written; + Put((ushort)endPoint.Port); } From 38dfa86b217062dcb290c290a14c82ccb7a9a43b Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 23 Mar 2026 10:23:23 +0100 Subject: [PATCH 136/200] Update docs --- LiteNetLib/ConnectionRequest.cs | 2 +- LiteNetLib/LiteNetManager.Socket.cs | 3 +-- LiteNetLib/LiteNetManager.cs | 8 ++++---- LiteNetLib/LiteNetPeer.cs | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 32b965eb..2c72d845 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -88,7 +88,7 @@ public LiteNetPeer Accept() /// Length of the data to be sent from the array. /// /// If , sends a single raw packet and immediately removes the request.
    - /// If , creates a temporary peer that sends a single rejection packet and lingers in memory until a timeout occurs to handle late-arriving packets. + /// If , creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets. /// public void Reject(byte[] rejectData, int start, int length, bool force) { diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index f77c015d..522e86a0 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -328,8 +328,7 @@ private void ReceiveLogic() /// /// When , disables internal background threads.
    /// You must manually call and .

    - /// Recommended for single-threaded environments like Unity or for - /// reducing multi-threading overhead and synchronization issues. + /// Can be used when e.g. 10,000 instances are running on the same machine, reducing the amount of threads used. /// public bool Start(IPAddress addressIPv4, IPAddress addressIPv6, int port, bool manualMode) { diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index e7b0102f..194b0b05 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -309,7 +309,7 @@ internal void DisconnectPeerForce(LiteNetPeer peer, /// The error code from the underlying socket, if any. /// /// If , immediately sets state to without sending a notification.
    - /// If , sends a single unreliable disconnect packet and sets state to . + /// If , sends unreliable disconnect packets until and sets state to . /// Peer will linger until to ignore late-arriving packets from the old session. /// /// Optional custom data to include in the disconnect packet. @@ -577,7 +577,7 @@ private void ProcessDelayedPackets() /// - /// Updates internal peer states, handles timeouts, and processes NTP requests. + /// Updates internal peer states, handles timeouts, processes NTP requests and sends buffered packets. /// /// Time passed since the last update frame. /// @@ -1296,10 +1296,10 @@ public void TriggerUpdate() => _updateTriggerEvent.Set(); /// - /// Reads data from the UDP sockets and processes pending events immediately. + /// Synchronizes arrived events from the background thread to your main-thread/ /// /// - /// Must be called continuously from the main loop if was set to . + /// Must be called continuously from the main loop if was set to to receive data from the UDP sockets. /// public void PollEvents() { diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index dacce2c6..8ca4e55c 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -706,7 +706,7 @@ internal virtual void AddToReliableChannelSendQueue(BaseChannel channel) /// Length of the data to send. /// /// If , immediately sets state to without sending a notification.
    - /// If , sends a single unreliable disconnect packet and sets state to + /// If , sends unreliable disconnect packets until a timeout occurs and sets state to /// Queued reliable packets are bypassed and dropped immediately. /// /// A indicating the state change transition. @@ -948,7 +948,7 @@ private void UpdateMtuLogic(float deltaTime) /// A directing how the manager should handle the request. /// /// If the state is , the peer lingers to ignore older connection requests - /// (where the packet timestamp is smaller than internal ), ensuring delayed or stale packets are dropped. + /// (where the packet timestamp is smaller than internal ), ensuring older connections are ignored. /// internal ConnectRequestResult ProcessConnectRequest(NetConnectRequestPacket connRequest) { From 2e33f8ec043a9990fb3df881357073fc75f93ddc Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:23:18 +0100 Subject: [PATCH 137/200] Update docs --- LiteNetLib/ConnectionRequest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 2c72d845..055eb5ca 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -118,7 +118,7 @@ public void RejectForce(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, true); /// - /// Rejects the connection immediately without reliability and without additional data. + /// Rejects the connection immediately without sending any packet. /// public void RejectForce() => Reject(null, 0, 0, true); @@ -138,7 +138,7 @@ public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); /// - /// Rejects the connection reliably without additional data. + /// Rejects the connection without sending any packet. /// public void Reject() => Reject(null, 0, 0, false); From 2f4da2345a7a747ac860bd4d499b6bb34e050f60 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:26:49 +0100 Subject: [PATCH 138/200] Update docs --- LiteNetLib/ConnectionRequest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 055eb5ca..118f2415 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -87,7 +87,7 @@ public LiteNetPeer Accept() /// Offset in the array. /// Length of the data to be sent from the array. /// - /// If , sends a single raw packet and immediately removes the request.
    + /// If , rejects the connection immediately without sending any packet.
    /// If , creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets. /// public void Reject(byte[] rejectData, int start, int length, bool force) @@ -138,7 +138,7 @@ public void RejectForce(NetDataWriter rejectData) => Reject(rejectData.Data, 0, rejectData.Length, true); /// - /// Rejects the connection without sending any packet. + /// Rejects the connection reliably without additional data. /// public void Reject() => Reject(null, 0, 0, false); From c3c41da136a1c42606c9307d08556b625560f98b Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Mon, 23 Mar 2026 11:29:42 +0100 Subject: [PATCH 139/200] Update docs --- LiteNetLib/ConnectionRequest.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 118f2415..3f770aa2 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -87,7 +87,7 @@ public LiteNetPeer Accept() /// Offset in the array. /// Length of the data to be sent from the array. /// - /// If , rejects the connection immediately without sending any packet.
    + /// If , immediately removes the request, if is not a reject packet is also sent.
    /// If , creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets. /// public void Reject(byte[] rejectData, int start, int length, bool force) @@ -108,7 +108,7 @@ public void Reject(byte[] rejectData, int start, int length) => Reject(rejectData, start, length, false); /// - /// Rejects the connection immediately without reliability. + /// Rejects the connection immediately without reliability. /// Minimizes resource usage by not creating an internal peer. /// /// Data to send with the rejection. From 6dd508e4362632575db6a741a2fea288af08e1a9 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Mon, 23 Mar 2026 12:34:57 +0200 Subject: [PATCH 140/200] generate docs --- .../api/LiteNetLib.LiteConnectionRequest.html | 71 +++++++++++++------ docs/api/LiteNetLib.LiteNetManager.html | 17 +++-- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/docs/api/LiteNetLib.LiteConnectionRequest.html b/docs/api/LiteNetLib.LiteConnectionRequest.html index 6eb76992..b624712a 100644 --- a/docs/api/LiteNetLib.LiteConnectionRequest.html +++ b/docs/api/LiteNetLib.LiteConnectionRequest.html @@ -213,7 +213,8 @@
    Returns

    Reject()

    -
    +

    Rejects the connection reliably without additional data.

    +
    Declaration
    @@ -223,7 +224,8 @@
    Declaration

    Reject(NetDataWriter)

    -
    +

    Rejects the connection reliably using data from a NetDataWriter.

    +
    Declaration
    @@ -242,7 +244,8 @@
    Parameters
    NetDataWriter rejectData - +

    Writer containing the data to send.

    + @@ -250,7 +253,8 @@
    Parameters

    Reject(byte[])

    -
    +

    Rejects the connection reliably.

    +
    Declaration
    @@ -269,7 +273,8 @@
    Parameters
    byte[] rejectData - +

    Data to send with the rejection.

    + @@ -277,7 +282,8 @@
    Parameters

    Reject(byte[], int, int)

    -
    +

    Rejects the connection reliably. Creates a temporary peer to handle packet loss.

    +
    Declaration
    @@ -296,17 +302,20 @@
    Parameters
    byte[] rejectData - +

    Data to send with the rejection.

    + int start - +

    Offset in the rejectData array.

    + int length - +

    Length of the data to be sent.

    + @@ -314,7 +323,8 @@
    Parameters

    Reject(byte[], int, int, bool)

    -
    +

    Rejects the connection request.

    +
    Declaration
    @@ -333,22 +343,27 @@
    Parameters
    byte[] rejectData - +

    Optional user data to send along with the rejection packet.

    + int start - +

    Offset in the rejectData array.

    + int length - +

    Length of the data to be sent from the rejectData array.

    + bool force - +

    If true, immediately removes the request, if rejectData is not null a reject packet is also sent.
    +If false, creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets.

    + @@ -356,7 +371,8 @@
    Parameters

    RejectForce()

    -
    +

    Rejects the connection immediately without sending any packet.

    +
    Declaration
    @@ -366,7 +382,8 @@
    Declaration

    RejectForce(NetDataWriter)

    -
    +

    Rejects the connection immediately without reliability using data from a NetDataWriter.

    +
    Declaration
    @@ -385,7 +402,8 @@
    Parameters
    NetDataWriter rejectData - +

    Writer containing the data to send.

    + @@ -393,7 +411,8 @@
    Parameters

    RejectForce(byte[])

    -
    +

    Rejects the connection immediately without reliability.

    +
    Declaration
    @@ -412,7 +431,8 @@
    Parameters
    byte[] rejectData - +

    Data to send with the rejection.

    + @@ -420,7 +440,9 @@
    Parameters

    RejectForce(byte[], int, int)

    -
    +

    Rejects the connection immediately without reliability. +Minimizes resource usage by not creating an internal peer.

    +
    Declaration
    @@ -439,17 +461,20 @@
    Parameters
    byte[] rejectData - +

    Data to send with the rejection.

    + int start - +

    Offset in the rejectData array.

    + int length - +

    Length of the data to be sent.

    + diff --git a/docs/api/LiteNetLib.LiteNetManager.html b/docs/api/LiteNetLib.LiteNetManager.html index cc9bd602..be29695b 100644 --- a/docs/api/LiteNetLib.LiteNetManager.html +++ b/docs/api/LiteNetLib.LiteNetManager.html @@ -2231,7 +2231,7 @@
    Returns

    ManualUpdate(float)

    -

    Update and send logic. Use this only when NetManager started in manual mode

    +

    Updates internal peer states, handles timeouts, processes NTP requests and sends buffered packets.

    Declaration
    @@ -2251,23 +2251,28 @@
    Parameters
    float elapsedMilliseconds -

    elapsed milliseconds since last update call

    +

    Time passed since the last update frame.

    +
    Remarks
    +

    Must be called continuously from the main loop if LiteNetLib.LiteNetManager._manualMode was set to true.

    +

    PollEvents()

    -

    Receive" pending events. Call this in game update code -In Manual mode it will call also socket Receive (which can be slow)

    +

    Synchronizes arrived events from the background thread to your main-thread/INetEventListener

    Declaration
    public void PollEvents()
    +
    Remarks
    +

    Must be called continuously from the main loop if LiteNetLib.LiteNetManager._manualMode was set to true to receive data from the UDP sockets.

    +
    @@ -3286,7 +3291,9 @@
    Parameters
    bool manualMode -

    mode of library

    +

    When true, disables internal background threads.
    +You must manually call PollEvents() and ManualUpdate(float).

    +Can be used when e.g. 10,000 instances are running on the same machine, reducing the amount of threads used.

    From 1da705560d02ac95a167fbd00974c7d6723b31c5 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 20:15:30 +0300 Subject: [PATCH 141/200] Use packet.Size for bounds check Fix a bounds check when merging packets by using packet.Size rather than packet.RawData.Length. This ensures the code checks against the actual packet payload length (Size) instead of the underlying buffer capacity, preventing potential reads past the valid packet data. --- LiteNetLib/LiteNetPeer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 8ca4e55c..334af37a 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -1049,7 +1049,7 @@ internal void ProcessPacket(NetPacket packet) break; pos += 2; - if (packet.RawData.Length - pos < size) + if (packet.Size - pos < size) break; NetPacket mergedPacket = NetManager.PoolGetPacket(size); From 7d7b08fb7509f9669a7442a19d5f7a9a63691ab0 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:14:53 +0300 Subject: [PATCH 142/200] Simplify IncomingFragments Replace the previous dual storage (small-array vs dictionary) with a single NetPacket[] Fragments in IncomingFragments and mark the class sealed. Remove Contains/TryGet/Set/Remove helpers and update RecycleAll to iterate, recycle and null entries. Update reassembly code to access the Fragments array directly, prevent duplicate fragment insertion, null out recycled fragments, and correct/clarify fragment size and position checks and error messages. These changes simplify memory handling and reduce branching/allocations during fragment assembly. --- LiteNetLib/LiteNetPeer.cs | 83 +++++++++++---------------------------- 1 file changed, 24 insertions(+), 59 deletions(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 96997b9e..fd4db9d4 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -98,17 +98,12 @@ private set private readonly object _mtuMutex = new object(); //Fragment - private class IncomingFragments + private sealed class IncomingFragments { - // Fragments with TotalFragments <= threshold use a fixed array (faster) - // Larger sets use a dictionary to avoid large upfront allocations - private const int ArrayThreshold = 64; - - private readonly NetPacket[] _array; - private readonly Dictionary _dict; - + public readonly NetPacket[] Fragments; public readonly ushort TotalFragments; public readonly byte ChannelId; + public int ReceivedCount; public int TotalSize; @@ -116,52 +111,19 @@ public IncomingFragments(ushort totalFragments, byte channelId) { TotalFragments = totalFragments; ChannelId = channelId; - if (totalFragments <= ArrayThreshold) - _array = new NetPacket[totalFragments]; - else - _dict = new Dictionary(); - } - - public bool Contains(ushort part) => - _array != null ? _array[part] != null : _dict.ContainsKey(part); - - public bool TryGet(ushort part, out NetPacket packet) - { - if (_array != null) - { - packet = _array[part]; - return packet != null; - } - return _dict.TryGetValue(part, out packet); - } - - public void Set(ushort part, NetPacket packet) - { - if (_array != null) - _array[part] = packet; - else - _dict[part] = packet; - } - - public void Remove(ushort part) - { - if (_array != null) - _array[part] = null; - else - _dict.Remove(part); + Fragments = new NetPacket[totalFragments]; } public void RecycleAll(LiteNetManager netManager) { - if (_array != null) + for (int i = 0; i < Fragments.Length; i++) { - foreach (var p in _array) - if (p != null) netManager.PoolRecycle(p); - } - else - { - foreach (var p in _dict.Values) - netManager.PoolRecycle(p); + NetPacket packet = Fragments[i]; + if (packet != null) + { + netManager.PoolRecycle(packet); + Fragments[i] = null; + } } } } @@ -851,13 +813,15 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) return; } - if (incomingFragments.Contains(p.FragmentPart)) + NetPacket[] fragments = incomingFragments.Fragments; + + if (fragments[p.FragmentPart] != null) { NetManager.PoolRecycle(p); return; } - incomingFragments.Set(p.FragmentPart, p); + fragments[p.FragmentPart] = p; incomingFragments.ReceivedCount++; incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize; @@ -877,23 +841,23 @@ void AbortReassembly(string error) int pos = 0; for (ushort i = 0; i < incomingFragments.TotalFragments; i++) { - if (!incomingFragments.TryGet(i, out var fragment)) + NetPacket fragment = fragments[i]; + if (fragment == null) { AbortReassembly($"Fragment {i} missing during reassembly"); return; } - int writtenSize = fragment.Size - NetConstants.FragmentedHeaderTotalSize; - - if (pos + writtenSize > resultingPacket.RawData.Length) + if (fragment.Size > fragment.RawData.Length) { - AbortReassembly($"Fragment error pos: {pos + writtenSize} >= resultPacketSize: {resultingPacket.RawData.Length}"); + AbortReassembly($"Fragment error size: {fragment.Size} > fragment.RawData.Length: {fragment.RawData.Length}"); return; } - if (fragment.Size > fragment.RawData.Length) + int writtenSize = fragment.Size - NetConstants.FragmentedHeaderTotalSize; + if (pos + writtenSize > resultingPacket.RawData.Length) { - AbortReassembly($"Fragment error size: {fragment.Size} > fragment.RawData.Length: {fragment.RawData.Length}"); + AbortReassembly($"Fragment error pos: {pos + writtenSize} >= resultPacketSize: {resultingPacket.RawData.Length}"); return; } @@ -903,10 +867,11 @@ void AbortReassembly(string error) resultingPacket.RawData, pos, writtenSize); + pos += writtenSize; NetManager.PoolRecycle(fragment); - incomingFragments.Remove(i); + fragments[i] = null; } _holdedFragments.Remove(packetFragId); From 70d02004abf8378691e6bf484e74d9b22227fcb7 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:22:30 +0300 Subject: [PATCH 143/200] Comments --- LiteNetLib/LiteNetPeer.cs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index fd4db9d4..eac387a5 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -797,6 +797,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) if (!_holdedFragments.TryGetValue(packetFragId, out var incomingFragments)) { + //Holded fragments limit reached if (_holdedFragments.Count >= NetConstants.MaxFragmentsInWindow * ChannelsCount * NetConstants.FragmentedChannelsCount) { NetManager.PoolRecycle(p); @@ -813,21 +814,30 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) return; } - NetPacket[] fragments = incomingFragments.Fragments; + //Cache + var fragments = incomingFragments.Fragments; + //Error check if (fragments[p.FragmentPart] != null) { NetManager.PoolRecycle(p); return; } + //Fill array fragments[p.FragmentPart] = p; + + //Increase received fragments count incomingFragments.ReceivedCount++; + + //Increase total size incomingFragments.TotalSize += p.Size - NetConstants.FragmentedHeaderTotalSize; + //Check for finish if (incomingFragments.ReceivedCount != incomingFragments.TotalFragments) return; + //Just simple packet NetPacket resultingPacket = NetManager.PoolGetPacket(incomingFragments.TotalSize); void AbortReassembly(string error) @@ -861,6 +871,7 @@ void AbortReassembly(string error) return; } + //Create resulting big packet Buffer.BlockCopy( fragment.RawData, NetConstants.FragmentedHeaderTotalSize, @@ -870,11 +881,15 @@ void AbortReassembly(string error) pos += writtenSize; + //Free memory NetManager.PoolRecycle(fragment); fragments[i] = null; } + //Clear memory _holdedFragments.Remove(packetFragId); + + //Send to process NetManager.CreateReceiveEvent(resultingPacket, method, (byte)(packetChannelId / NetConstants.ChannelTypeCount), 0, this); } else //Just simple packet From 52d53635abb3851c0a1c41bbe6090a392d48b1ce Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:23:56 +0300 Subject: [PATCH 144/200] Comment x2 --- LiteNetLib/LiteNetPeer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index eac387a5..185c553b 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -791,6 +791,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) } NetDebug.Write($"Fragment. Id: {p.FragmentId}, Part: {p.FragmentPart}, Total: {p.FragmentsTotal}"); + //Get needed array from dictionary ushort packetFragId = p.FragmentId; byte packetChannelId = p.ChannelId; From ed7e0e6c35160d85b5b41ea988c926a5bb027f4a Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:24:59 +0300 Subject: [PATCH 145/200] Old code style --- LiteNetLib/LiteNetPeer.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 185c553b..bbf6dd3c 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -791,11 +791,10 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) } NetDebug.Write($"Fragment. Id: {p.FragmentId}, Part: {p.FragmentPart}, Total: {p.FragmentsTotal}"); - //Get needed array from dictionary + //Get needed array from dictionary ushort packetFragId = p.FragmentId; byte packetChannelId = p.ChannelId; - if (!_holdedFragments.TryGetValue(packetFragId, out var incomingFragments)) { //Holded fragments limit reached From 845db312a638e0f5a24b662e70966c4a802652d8 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:25:39 +0300 Subject: [PATCH 146/200] Old log --- LiteNetLib/LiteNetPeer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index bbf6dd3c..3ee24789 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -801,6 +801,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) if (_holdedFragments.Count >= NetConstants.MaxFragmentsInWindow * ChannelsCount * NetConstants.FragmentedChannelsCount) { NetManager.PoolRecycle(p); + //NetDebug.WriteError($"Holded fragments limit reached ({_holdedFragments.Count}/{(NetConstants.DefaultWindowSize / 2) * ChannelsCount * NetConstants.FragmentedChannelsCount}). Dropping fragment id: {packetFragId}"); return; } From 8258bdee8d4293370909a65f585ba81fd1522b2e Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:27:22 +0300 Subject: [PATCH 147/200] updates --- LiteNetLib/LiteNetPeer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 3ee24789..b395935c 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -791,7 +791,6 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) } NetDebug.Write($"Fragment. Id: {p.FragmentId}, Part: {p.FragmentPart}, Total: {p.FragmentsTotal}"); - //Get needed array from dictionary ushort packetFragId = p.FragmentId; byte packetChannelId = p.ChannelId; @@ -822,6 +821,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) if (fragments[p.FragmentPart] != null) { NetManager.PoolRecycle(p); + NetDebug.WriteError("Invalid fragment packet"); return; } From 0ee4563f81994dc26f57946992b0e47996013d82 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:28:00 +0300 Subject: [PATCH 148/200] latest mb --- LiteNetLib/LiteNetPeer.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index b395935c..89b5b241 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -791,6 +791,7 @@ internal void AddReliablePacket(DeliveryMethod method, NetPacket p) } NetDebug.Write($"Fragment. Id: {p.FragmentId}, Part: {p.FragmentPart}, Total: {p.FragmentsTotal}"); + //Get needed array from dictionary ushort packetFragId = p.FragmentId; byte packetChannelId = p.ChannelId; From 7e650ea9e0d41fef564f0f2f2ca45df76b9eb8b4 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 21:45:31 +0300 Subject: [PATCH 149/200] Add ThrowNotEnoughData helper and uint check Replace the previous bounds check in EnsureAvailable with an unsigned comparison against a local available variable and extract the throw into a separate ThrowNotEnoughData method. The new helper is marked NoInlining and includes XML documentation. This reduces duplicated throw logic in hot paths and makes the bounds-check semantics clearer and more JIT-friendly. --- LiteNetLib/Utils/NetDataReader.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index a93114fa..0c2fe732 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -93,9 +93,21 @@ public int AvailableBytes [MethodImpl(MethodImplOptions.AggressiveInlining)] private void EnsureAvailable(int count) { - if (count < 0 || count > AvailableBytes) - throw new InvalidOperationException( - $"Not enough data to read {count} byte(s). Position={_position}, DataSize={_dataSize}"); + int available = _dataSize - _position; + if ((uint)count > (uint)available) + ThrowNotEnoughData(count); + } + + /// + /// Throws an indicating that there is not enough data to read. + /// + /// The number of bytes that were attempted to be read. + /// Always thrown. + [MethodImpl(MethodImplOptions.NoInlining)] + private void ThrowNotEnoughData(int count) + { + throw new InvalidOperationException( + $"Not enough data to read {count} byte(s). Position={_position}, DataSize={_dataSize}"); } /// From ba43052a76b4e312484ca6906b3bdcdc76b2f545 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:00:22 +0300 Subject: [PATCH 150/200] Fix XML doc tag in NetDataReader Correct a typo in the XML documentation of LiteNetLib/Utils/NetDataReader.cs by replacing an invalid attribute with . This fixes documentation warnings and ensures the class reference renders correctly. --- LiteNetLib/Utils/NetDataReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 0c2fe732..a6327657 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -182,7 +182,7 @@ public void Get(out T result) where T : struct, INetSerializable } /// - /// Deserializes a that implements using a provided constructor. + /// Deserializes a that implements using a provided constructor. /// /// A type implementing . /// The deserialized instance output. From e723df27e6df4a46355f72d6acb004e26cba71a2 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:01:21 +0300 Subject: [PATCH 151/200] Call Get(out ...) overloads in Get methods Replace direct instantiation and obj.Deserialize(this) with calls to existing Get(out ...) overloads in both struct and class INetSerializable Get methods. This removes duplicated deserialization code and centralizes behavior without changing functionality. --- LiteNetLib/Utils/NetDataReader.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index a6327657..7de98580 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -547,9 +547,8 @@ public ArraySegment GetRemainingBytesSegment() /// The deserialized . public T Get() where T : struct, INetSerializable { - var obj = default(T); - obj.Deserialize(this); - return obj; + Get(out T result); + return result; } /// @@ -560,9 +559,8 @@ public T Get() where T : struct, INetSerializable /// A new instance of . public T Get(Func constructor) where T : class, INetSerializable { - var obj = constructor(); - obj.Deserialize(this); - return obj; + Get(out T result, constructor); + return result; } /// From cb68beda3a6c73ab06026d233a7d25eae8a0b768 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:04:49 +0300 Subject: [PATCH 152/200] Simplify GetIPEndPoint and add IP size constants Introduce IPv4Size and IPv6Size constants and consolidate IPv4/IPv6 branching in GetIPEndPoint. Read the IP version flag, compute the address size, ensure buffer availability, construct the IPAddress from a ReadOnlySpan, and advance the position. Removes duplicated code and magic numbers while preserving existing behavior. --- LiteNetLib/Utils/NetDataReader.cs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 7de98580..ff5d6b9c 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -13,6 +13,9 @@ public class NetDataReader protected int _dataSize; protected int _offset; + private const int IPv4Size = 4; + private const int IPv6Size = 16; + /// /// Gets the internal array containing the raw network data. /// @@ -209,21 +212,13 @@ public void Get(out T result, Func constructor) where T : class, INetSeria /// public IPEndPoint GetIPEndPoint() { - IPAddress address; - //IPv4 - if (GetByte() == 0) - { - EnsureAvailable(4); - address = new IPAddress(new ReadOnlySpan(_data, _position, 4)); - _position += 4; - } - //IPv6 - else - { - EnsureAvailable(16); - address = new IPAddress(new ReadOnlySpan(_data, _position, 16)); - _position += 16; - } + bool isIPv4 = GetByte() == 0; + + int size = isIPv4 ? IPv4Size : IPv6Size; + EnsureAvailable(size); + + IPAddress address = new IPAddress(new ReadOnlySpan(_data, _position, size)); + _position += size; return new IPEndPoint(address, GetUShort()); } From d7542e3ad613af7423c5340631890f7d3f2350b0 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:16:12 +0300 Subject: [PATCH 153/200] Add bounds check to GetByte Call EnsureAvailable(1) before reading from the internal buffer in NetDataReader.GetByte to prevent out-of-range reads and provide consistent error handling. The method still increments the read position after returning the byte. --- LiteNetLib/Utils/NetDataReader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index ff5d6b9c..74f5f5bc 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -268,7 +268,11 @@ public IPEndPoint GetIPEndPoint() public void Get(out Guid result) => result = GetGuid(); /// Reads the next from the buffer. - public byte GetByte() => _data[_position++]; + public byte GetByte() + { + EnsureAvailable(1); + return _data[_position++]; + } /// Reads the next from the buffer. public sbyte GetSByte() => (sbyte)GetByte(); From 62b45fe6e9c95d0f199c6db115edf96d24026a0b Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:20:33 +0300 Subject: [PATCH 154/200] Check overflow and availability in GetUnmanagedArray Use checked() when computing byteLength and call EnsureAvailable(byteLength) before taking a span. This prevents silent integer overflow on length * sizeof(T) and verifies there are enough bytes available for MemoryMarshal.Cast and subsequent array creation in GetUnmanagedArray(). --- LiteNetLib/Utils/NetDataReader.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 74f5f5bc..a6559922 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -285,7 +285,9 @@ public byte GetByte() public unsafe T[] GetUnmanagedArray() where T : unmanaged { ushort length = GetUShort(); - int byteLength = length * sizeof(T); + int byteLength = checked(length * sizeof(T)); + EnsureAvailable(byteLength); + ReadOnlySpan slice = _data.AsSpan(_position, byteLength); T[] result = MemoryMarshal.Cast(slice) .ToArray(); From 15a9a920a9e926026fcfa7a24f049fc4ff82bff7 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:21:04 +0300 Subject: [PATCH 155/200] Replace magic 16 with GuidSize constant Introduce a GuidSize constant (16) and use it in GetGuid() instead of hard-coded 16s. This improves readability and avoids repeated magic numbers when ensuring availability, constructing the Guid from the data span, and advancing the read position. --- LiteNetLib/Utils/NetDataReader.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index a6559922..f6827450 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -15,6 +15,7 @@ public class NetDataReader private const int IPv4Size = 4; private const int IPv6Size = 16; + private const int GuidSize = 16; /// /// Gets the internal array containing the raw network data. @@ -511,9 +512,9 @@ public string GetLargeString() /// The deserialized . public Guid GetGuid() { - EnsureAvailable(16); - var result = new Guid(_data.AsSpan(_position, 16)); - _position += 16; + EnsureAvailable(GuidSize); + var result = new Guid(_data.AsSpan(_position, GuidSize)); + _position += GuidSize; return result; } From 20d45eb892b0bfc4661d8d02432e99347f164f0c Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:23:12 +0300 Subject: [PATCH 156/200] Use named constants for IP and GUID sizes Introduce IPv4Size (4), IPv6Size (16) and GuidSize (16) constants in NetDataWriter.cs and replace magic numbers with these constants in Put(Guid) and when determining addressSize for IPEndPoint. This improves readability and maintainability by avoiding literal size values. --- LiteNetLib/Utils/NetDataWriter.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 18a9fc6a..00365548 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -14,6 +14,10 @@ public class NetDataWriter private const int InitialSize = 64; private readonly bool _autoResize; + private const int IPv4Size = 4; + private const int IPv6Size = 16; + private const int GuidSize = 16; + /// /// Gets the total capacity of the internal buffer. /// @@ -272,9 +276,9 @@ public int SetPosition(int position) public void Put(Guid value) { if (_autoResize) - ResizeIfNeed(_position + 16); + ResizeIfNeed(_position + GuidSize); value.TryWriteBytes(_data.AsSpan(_position)); - _position += 16; + _position += GuidSize; } /// @@ -516,12 +520,12 @@ public void Put(IPEndPoint endPoint) if (endPoint.AddressFamily == AddressFamily.InterNetwork) { - addressSize = 4; + addressSize = IPv4Size; familyFlag = 0; } else if (endPoint.AddressFamily == AddressFamily.InterNetworkV6) { - addressSize = 16; + addressSize = IPv6Size; familyFlag = 1; } else From d615f1068e455d7a05633cddb5c081df89984686 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:24:20 +0300 Subject: [PATCH 157/200] Code style --- LiteNetLib/Utils/NetDataReader.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index f6827450..a397fafa 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -286,6 +286,7 @@ public byte GetByte() public unsafe T[] GetUnmanagedArray() where T : unmanaged { ushort length = GetUShort(); + int byteLength = checked(length * sizeof(T)); EnsureAvailable(byteLength); From 72dfcff8fac0bb96839468747051e90b655a1bb6 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:33:16 +0300 Subject: [PATCH 158/200] Validate buffer and fix GetStringArray locals Add EnsureAvailable checks to both GetStringArray overloads to verify there are enough bytes for the array string lengths before reading (uses checked(length * sizeof(ushort)) to catch overflows). Also rename the local array variable from `arr` to `result` and return it, cleaning up the methods and improving safety against buffer overruns. --- LiteNetLib/Utils/NetDataReader.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index a397fafa..c2be230d 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -388,12 +388,15 @@ public T[] GetArray(Func constructor) where T : class, INetSerializable public string[] GetStringArray() { ushort length = GetUShort(); - string[] arr = new string[length]; + EnsureAvailable(checked(length * sizeof(ushort))); // 2 bytes (ushort) for string length + + string[] result = new string[length]; for (int i = 0; i < length; i++) { - arr[i] = GetString(); + result[i] = GetString(); } - return arr; + + return result; } /// @@ -407,12 +410,15 @@ public string[] GetStringArray() public string[] GetStringArray(int maxStringLength) { ushort length = GetUShort(); - string[] arr = new string[length]; + EnsureAvailable(checked(length * sizeof(ushort))); // 2 bytes (ushort) for string length + + string[] result = new string[length]; for (int i = 0; i < length; i++) { - arr[i] = GetString(maxStringLength); + result[i] = GetString(maxStringLength); } - return arr; + + return result; } /// Reads a value from the current position. From 19af39613b82172d25410aeef64c3ef5ad7a470f Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:37:52 +0300 Subject: [PATCH 159/200] Use AvailableBytes for remaining bytes APIs Replace direct calculation (_dataSize - _position) with the AvailableBytes property in GetRemainingBytesSpan and GetRemainingBytesMemory. This deduplicates logic, improves clarity, and ensures both methods use the same availability check when returning the remaining data slice before advancing the position. --- LiteNetLib/Utils/NetDataReader.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index c2be230d..e500a3b7 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -579,7 +579,7 @@ public T Get(Func constructor) where T : class, INetSerializable [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan GetRemainingBytesSpan() { - var result = new ReadOnlySpan(_data, _position, _dataSize - _position); + var result = new ReadOnlySpan(_data, _position, AvailableBytes); _position = _dataSize; return result; } @@ -591,7 +591,7 @@ public ReadOnlySpan GetRemainingBytesSpan() [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory GetRemainingBytesMemory() { - var result = new ReadOnlyMemory(_data, _position, _dataSize - _position); + var result = new ReadOnlyMemory(_data, _position, AvailableBytes); _position = _dataSize; return result; } From cf9a9689bf8eca0d96f6775668b4cad6d4622a9d Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:41:02 +0300 Subject: [PATCH 160/200] Return Array.Empty for zero-length reads Avoid allocating a new byte[] when no data remains by returning Array.Empty() for size == 0. Also rename the temporary buffer to result for clarity; behavior for non-zero reads is unchanged (copy remaining bytes, advance position to end). This reduces allocations for empty reads. --- LiteNetLib/Utils/NetDataReader.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index e500a3b7..d49ac0d5 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -606,10 +606,13 @@ public ReadOnlyMemory GetRemainingBytesMemory() public byte[] GetRemainingBytes() { int size = _dataSize - _position; - byte[] outgoingData = new byte[size]; - Buffer.BlockCopy(_data, _position, outgoingData, 0, size); + if (size == 0) + return Array.Empty(); + + byte[] result = new byte[size]; + Buffer.BlockCopy(_data, _position, result, 0, size); _position = _dataSize; - return outgoingData; + return result; } /// From 13e6f9149b783caad39faa3ac77c2a15a3a4f27f Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:49:32 +0300 Subject: [PATCH 161/200] Use GetUnmanaged for GetEnum Replace the previous platform-specific unsafe read logic in GetEnum() with a direct call to GetUnmanaged(). This centralizes unmanaged enum reading, removes the NET8 conditional (Unsafe.ReadUnaligned / fixed pointer) and reduces duplicated unsafe buffer-reading code without changing behavior. --- LiteNetLib/Utils/NetDataReader.cs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index d49ac0d5..70dee381 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -709,20 +709,7 @@ public unsafe T GetUnmanaged() where T : unmanaged /// /// An unmanaged enum type to read. /// The enum value read from the buffer. - public unsafe T GetEnum() where T : unmanaged, Enum - { - int size = sizeof(T); - ReadOnlySpan span = new ReadOnlySpan(_data, _position, size); - _position += size; -#if NET8_0_OR_GREATER - return Unsafe.ReadUnaligned(ref MemoryMarshal.GetReference(span)); -#else - fixed (byte* ptr = span) - { - return *(T*)ptr; - } -#endif - } + public unsafe T GetEnum() where T : unmanaged, Enum => GetUnmanaged(); #endregion From d933a4e92f118aee77bda810632f271f710d5841 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 22:56:21 +0300 Subject: [PATCH 162/200] Code style --- LiteNetLib/Utils/NetDataReader.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 70dee381..60ba6748 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -800,9 +800,11 @@ public unsafe T PeekUnmanaged() where T : unmanaged return value; #endif } + #endregion #region TryGetMethods + /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . @@ -1032,6 +1034,7 @@ public bool TryGetBytesWithLength(out byte[] result) result = null; return false; } + #endregion /// Clears the reader state and releases the reference to the internal buffer. From 0c4fcc23fef0c4008bde180d944d6207fd23b5fd Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:10:30 +0300 Subject: [PATCH 163/200] Use GetSByte() in NetDataReader.Get(out sbyte) Replace casting from GetByte() with a direct call to GetSByte() in LiteNetLib/Utils/NetDataReader.cs. This ensures signed byte values are read using the dedicated reader method (preserving correct sign/semantics) and keeps the reading logic consistent. --- LiteNetLib/Utils/NetDataReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 60ba6748..49923548 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -227,7 +227,7 @@ public IPEndPoint GetIPEndPoint() public void Get(out byte result) => result = GetByte(); /// Reads an and assigns it to . - public void Get(out sbyte result) => result = (sbyte)GetByte(); + public void Get(out sbyte result) => result = GetSByte(); /// Reads a and assigns it to . public void Get(out bool result) => result = GetBool(); From b02d4b5a90ac4e2b093a4f32b7b6cf72aaa02634 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:11:01 +0300 Subject: [PATCH 164/200] Reposition GetByte/GetSByte in NetDataReader Move GetByte and GetSByte methods within LiteNetLib/Utils/NetDataReader.cs so they are grouped with other primitive read methods (placed before GetBool). This is a non-functional refactor to improve code organization and readability; no logic changes were made. --- LiteNetLib/Utils/NetDataReader.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 49923548..4e81f533 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -268,16 +268,6 @@ public IPEndPoint GetIPEndPoint() /// Reads a and assigns it to . public void Get(out Guid result) => result = GetGuid(); - /// Reads the next from the buffer. - public byte GetByte() - { - EnsureAvailable(1); - return _data[_position++]; - } - - /// Reads the next from the buffer. - public sbyte GetSByte() => (sbyte)GetByte(); - /// /// Reads an array of unmanaged values prefixed by a length. /// @@ -421,6 +411,16 @@ public string[] GetStringArray(int maxStringLength) return result; } + /// Reads the next from the buffer. + public byte GetByte() + { + EnsureAvailable(1); + return _data[_position++]; + } + + /// Reads the next from the buffer. + public sbyte GetSByte() => (sbyte)GetByte(); + /// Reads a value from the current position. /// if the byte is 1; otherwise, . public bool GetBool() => GetByte() == 1; From 8b4d4399089e02b58de776599ac3b51cf4aa3599 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:11:49 +0300 Subject: [PATCH 165/200] Use PeekByte/PeekUShort in Peek methods Refactor PeekSByte, PeekBool and PeekChar to call existing PeekByte()/PeekUShort() instead of directly accessing _data or PeekUnmanaged(). This centralizes byte/ushort read logic (and any bounds/validation behavior) to reduce duplication and potential subtle bugs while preserving external behavior. --- LiteNetLib/Utils/NetDataReader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 4e81f533..b4bdaef9 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -719,13 +719,13 @@ public unsafe T GetUnmanaged() where T : unmanaged public byte PeekByte() => _data[_position]; /// Reads the at the current position without advancing the . - public sbyte PeekSByte() => (sbyte)_data[_position]; + public sbyte PeekSByte() => (sbyte)PeekByte(); /// Reads the at the current position without advancing the . - public bool PeekBool() => _data[_position] == 1; + public bool PeekBool() => PeekByte() == 1; /// Reads the at the current position without advancing the . - public char PeekChar() => PeekUnmanaged(); + public char PeekChar() => (char)PeekUShort(); /// Reads the at the current position without advancing the . public ushort PeekUShort() => PeekUnmanaged(); From a834bd72918814068d6b3b1622aea5155b999bfa Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:14:07 +0300 Subject: [PATCH 166/200] Update NetDataReader.cs --- LiteNetLib/Utils/NetDataReader.cs | 118 ++++++++++-------------------- 1 file changed, 38 insertions(+), 80 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index b4bdaef9..b29f0e3b 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -864,114 +864,42 @@ public bool TryGetChar(out char result) /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetShort(out short result) - { - if (AvailableBytes >= 2) - { - result = GetShort(); - return true; - } - result = 0; - return false; - } + public bool TryGetShort(out short result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetUShort(out ushort result) - { - if (AvailableBytes >= 2) - { - result = GetUShort(); - return true; - } - result = 0; - return false; - } + public bool TryGetUShort(out ushort result) => TryGetUnmanaged(out result); /// Attempts to read an without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetInt(out int result) - { - if (AvailableBytes >= 4) - { - result = GetInt(); - return true; - } - result = 0; - return false; - } + public bool TryGetInt(out int result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetUInt(out uint result) - { - if (AvailableBytes >= 4) - { - result = GetUInt(); - return true; - } - result = 0; - return false; - } + public bool TryGetUInt(out uint result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetLong(out long result) - { - if (AvailableBytes >= 8) - { - result = GetLong(); - return true; - } - result = 0; - return false; - } + public bool TryGetLong(out long result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetULong(out ulong result) - { - if (AvailableBytes >= 8) - { - result = GetULong(); - return true; - } - result = 0; - return false; - } + public bool TryGetULong(out ulong result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetFloat(out float result) - { - if (AvailableBytes >= 4) - { - result = GetFloat(); - return true; - } - result = 0; - return false; - } + public bool TryGetFloat(out float result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetDouble(out double result) - { - if (AvailableBytes >= 8) - { - result = GetDouble(); - return true; - } - result = 0; - return false; - } + public bool TryGetDouble(out double result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or if failed. @@ -1035,6 +963,36 @@ public bool TryGetBytesWithLength(out byte[] result) return false; } + /// + /// Attempts to read a value of type from the internal byte buffer at the current position, + /// advancing the position by the size of if successful. + /// + /// An unmanaged value type to read from the buffer. + /// When this method returns, contains the value read from the buffer, or the default value if the read failed. + /// if enough data was available to read the value; otherwise, . + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public unsafe bool TryGetUnmanaged(out T result) where T : unmanaged + { + int size = sizeof(T); + if (AvailableBytes < size) + { + result = default; + return false; + } + +#if NET8_0_OR_GREATER + result = Unsafe.ReadUnaligned(ref _data[_position]); +#else + fixed (byte* ptr = &_data[_position]) + { + result = *(T*)ptr; + } +#endif + + _position += size; + return true; + } + #endregion /// Clears the reader state and releases the reference to the internal buffer. From a9a8ed9c44b4d949ef3acfdf5b1ed3d43821f268 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:17:37 +0300 Subject: [PATCH 167/200] Remove magic numbers --- LiteNetLib/Utils/NetDataReader.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index b29f0e3b..560281e2 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -763,9 +763,9 @@ public string PeekString(int maxLength) return string.Empty; int actualSize = size - 1; - return (maxLength > 0 && NetDataWriter.uTF8Encoding.GetCharCount(_data, _position + 2, actualSize) > maxLength) + return (maxLength > 0 && NetDataWriter.uTF8Encoding.GetCharCount(_data, _position + sizeof(ushort), actualSize) > maxLength) ? string.Empty - : NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); + : NetDataWriter.uTF8Encoding.GetString(_data, _position + sizeof(ushort), actualSize); } /// @@ -778,7 +778,7 @@ public string PeekString() return string.Empty; int actualSize = size - 1; - return NetDataWriter.uTF8Encoding.GetString(_data, _position + 2, actualSize); + return NetDataWriter.uTF8Encoding.GetString(_data, _position + sizeof(ushort), actualSize); } /// From 0765bb421b9ac98797bb8467acfb93116bf91de9 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:19:25 +0300 Subject: [PATCH 168/200] Code style --- LiteNetLib/Utils/NetDataReader.cs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 560281e2..a7ff4018 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -906,19 +906,23 @@ public bool TryGetChar(out char result) /// if enough data was available; otherwise, . public bool TryGetString(out string result) { - if (AvailableBytes >= 2) + if (AvailableBytes < sizeof(ushort)) { - ushort strSize = PeekUShort(); - int actualSize = strSize == 0 ? 0 : strSize - 1; + result = null; + return false; + } - if (AvailableBytes >= 2 + actualSize) - { - result = GetString(); - return true; - } + ushort size = PeekUShort(); + int actualSize = size == 0 ? 0 : size - 1; + + if (AvailableBytes < sizeof(ushort) + actualSize) + { + result = null; + return false; } - result = null; - return false; + + result = GetString(); + return true; } /// Attempts to read a array without throwing an exception. From 175d609967f5d8635b251b512300648924d770e9 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:21:12 +0300 Subject: [PATCH 169/200] Code style --- LiteNetLib/Utils/NetDataReader.cs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index a7ff4018..279e45dc 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -954,17 +954,21 @@ public bool TryGetStringArray(out string[] result) /// if enough data was available; otherwise, . public bool TryGetBytesWithLength(out byte[] result) { - if (AvailableBytes >= 2) + if (AvailableBytes < sizeof(ushort)) { - ushort length = PeekUShort(); - if (AvailableBytes >= 2 + length) - { - result = GetBytesWithLength(); - return true; - } + result = null; + return false; } - result = null; - return false; + + ushort length = PeekUShort(); + if (AvailableBytes < sizeof(ushort) + length) + { + result = null; + return false; + } + + result = GetBytesWithLength(); + return true; } /// From e8387e0cee324e9ad65155ac5c7d587d86eddca9 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Tue, 24 Mar 2026 23:25:52 +0300 Subject: [PATCH 170/200] TryGetStringArray roll back fix --- LiteNetLib/Utils/NetDataReader.cs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 279e45dc..ac91acef 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -930,22 +930,34 @@ public bool TryGetString(out string result) /// if enough data was available; otherwise, . public bool TryGetStringArray(out string[] result) { - if (!TryGetUShort(out ushort strArrayLength)) + if (AvailableBytes < sizeof(ushort)) { result = null; return false; } - result = new string[strArrayLength]; - for (int i = 0; i < strArrayLength; i++) + int startPosition = _position; + + ushort length = GetUShort(); + if (AvailableBytes < checked(length * sizeof(ushort))) // 2 bytes (ushort) for string length + { + _position = startPosition; // Roll back to the original position + result = null; + return false; + } + + string[] values = new string[length]; + for (int i = 0; i < length; i++) { - if (!TryGetString(out result[i])) + if (!TryGetString(out values[i])) { + _position = startPosition; // Roll back to the original position result = null; return false; } } + result = values; return true; } From ee593d1c180b297139fe2dafd9760a8cdfffef03 Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 25 Mar 2026 14:56:01 +0200 Subject: [PATCH 171/200] Update LiteNetLib/Utils/NetDataReader.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- LiteNetLib/Utils/NetDataReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index ac91acef..ae17b689 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -98,7 +98,7 @@ public int AvailableBytes private void EnsureAvailable(int count) { int available = _dataSize - _position; - if ((uint)count > (uint)available) + if (count < 0 || available < 0 || count > available) ThrowNotEnoughData(count); } From 7e71c26e9c81f53a5fcf6a4314204f28b0b9d3c7 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Wed, 25 Mar 2026 15:25:21 +0200 Subject: [PATCH 172/200] update version to 2.1.0 --- LiteNetLib/LiteNetLib.csproj | 6 +- docs/api/LiteNetLib.NetPacketReader.html | 15 +++-- docs/api/LiteNetLib.Utils.NetDataReader.html | 64 +++++++++++++++++++- docs/xrefmap.yml | 16 +++++ 4 files changed, 91 insertions(+), 10 deletions(-) diff --git a/LiteNetLib/LiteNetLib.csproj b/LiteNetLib/LiteNetLib.csproj index a896bb08..e53cde48 100644 --- a/LiteNetLib/LiteNetLib.csproj +++ b/LiteNetLib/LiteNetLib.csproj @@ -10,11 +10,11 @@ true 1701;1702;1705;1591 - 2.0.2 + 2.1.0 Lite reliable UDP library for Mono and .NET true true - 2.0.2 + 2.1.0 @@ -33,7 +33,7 @@ true $(DefineConstants);LITENETLIB_UNSAFE udp reliable-udp network - https://github.com/RevenantX/LiteNetLib/releases/tag/2.0.2 + https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.0 git https://github.com/RevenantX/LiteNetLib https://github.com/RevenantX/LiteNetLib diff --git a/docs/api/LiteNetLib.NetPacketReader.html b/docs/api/LiteNetLib.NetPacketReader.html index a2634d2c..9a8ae4b3 100644 --- a/docs/api/LiteNetLib.NetPacketReader.html +++ b/docs/api/LiteNetLib.NetPacketReader.html @@ -177,12 +177,6 @@
    Inherited Members
    - - @@ -228,6 +222,12 @@
    Inherited Members
    + + @@ -402,6 +402,9 @@
    Inherited Members
    + diff --git a/docs/api/LiteNetLib.Utils.NetDataReader.html b/docs/api/LiteNetLib.Utils.NetDataReader.html index 4b8e7acb..e12c546e 100644 --- a/docs/api/LiteNetLib.Utils.NetDataReader.html +++ b/docs/api/LiteNetLib.Utils.NetDataReader.html @@ -2560,7 +2560,7 @@
    Type Parameters

    Get<T>(out T, Func<T>)

    -

    Deserializes a that implements INetSerializable using a provided constructor.

    +

    Deserializes a class that implements INetSerializable using a provided constructor.

    Declaration
    @@ -3868,6 +3868,68 @@
    Returns
    + + +

    TryGetUnmanaged<T>(out T)

    +

    Attempts to read a value of type T from the internal byte buffer at the current position, +advancing the position by the size of T if successful.

    +
    +
    +
    Declaration
    +
    +
    public bool TryGetUnmanaged<T>(out T result) where T : unmanaged
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    Tresult

    When this method returns, contains the value read from the buffer, or the default value if the read failed.

    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    bool

    true if enough data was available to read the value; otherwise, false.

    +
    +
    Type Parameters
    + + + + + + + + + + + + + +
    NameDescription
    T

    An unmanaged value type to read from the buffer.

    +
    +
    diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index c0c86392..3dde95bc 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -5696,6 +5696,22 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.TryGetUShort nameWithType: NetDataReader.TryGetUShort +- uid: LiteNetLib.Utils.NetDataReader.TryGetUnmanaged* + name: TryGetUnmanaged + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_TryGetUnmanaged_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.TryGetUnmanaged + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.TryGetUnmanaged + nameWithType: NetDataReader.TryGetUnmanaged +- uid: LiteNetLib.Utils.NetDataReader.TryGetUnmanaged``1(``0@) + name: TryGetUnmanaged(out T) + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_TryGetUnmanaged__1___0__ + commentId: M:LiteNetLib.Utils.NetDataReader.TryGetUnmanaged``1(``0@) + name.vb: TryGetUnmanaged(Of T)(T) + fullName: LiteNetLib.Utils.NetDataReader.TryGetUnmanaged(out T) + fullName.vb: LiteNetLib.Utils.NetDataReader.TryGetUnmanaged(Of T)(T) + nameWithType: NetDataReader.TryGetUnmanaged(out T) + nameWithType.vb: NetDataReader.TryGetUnmanaged(Of T)(T) - uid: LiteNetLib.Utils.NetDataReader.UserDataOffset name: UserDataOffset href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_UserDataOffset From 56271b58b6a3dafb80ba54f322a11970ffdc7493 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 19:34:11 +0300 Subject: [PATCH 173/200] Update NetDataWriter.cs --- LiteNetLib/Utils/NetDataWriter.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 00365548..80eed775 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -562,16 +562,14 @@ public void PutLargeString(string value) Put(0); return; } + int size = uTF8Encoding.GetByteCount(value); - if (size == 0) - { - Put(0); - return; - } Put(size); + if (_autoResize) ResizeIfNeed(_position + size); - uTF8Encoding.GetBytes(value, 0, size, _data, _position); + + uTF8Encoding.GetBytes(value, 0, value.Length, _data, _position); _position += size; } From 044b03f08a797ea4b40837876c1f113a428d3d22 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Wed, 25 Mar 2026 18:56:14 +0200 Subject: [PATCH 174/200] simplify fast bitConverter. Remove BIGENDIAN checks because BIGENDIAN is deprecated. Fixes for unity --- LiteNetLib/Utils/FastBitConverter.cs | 146 ++------------------------- 1 file changed, 6 insertions(+), 140 deletions(-) diff --git a/LiteNetLib/Utils/FastBitConverter.cs b/LiteNetLib/Utils/FastBitConverter.cs index b067a3db..1a6c3287 100644 --- a/LiteNetLib/Utils/FastBitConverter.cs +++ b/LiteNetLib/Utils/FastBitConverter.cs @@ -1,13 +1,13 @@ using System; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; +#if UNITY_ANDROID +using Unity.Collections.LowLevel.Unsafe; +#endif namespace LiteNetLib.Utils { public static class FastBitConverter { -#if (LITENETLIB_UNSAFE || NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER) && !BIGENDIAN -#if LITENETLIB_UNSAFE [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged { @@ -16,12 +16,10 @@ public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) whe ThrowIndexOutOfRangeException(); #if NET8_0_OR_GREATER Unsafe.WriteUnaligned(ref bytes[startIndex], value); -#elif NETCOREAPP3_1 || NET5_0 || NETCOREAPP3_0_OR_GREATER - Unsafe.As(ref bytes[startIndex]) = value; #else fixed (byte* ptr = &bytes[startIndex]) { -#if UNITY_ANDROID + #if UNITY_ANDROID // On some android systems, assigning *(T*)ptr throws a NRE if // the ptr isn't aligned (i.e. if Position is 1,2,3,5, etc.). // Here we have to use memcpy. @@ -33,145 +31,13 @@ public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) whe // value types, but all blittable types are anyway. T* valueBuffer = stackalloc T[1] { value }; UnsafeUtility.MemCpy(ptr, valueBuffer, size); -#else + #else *(T*)ptr = value; -#endif + #endif } #endif } -#else - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged - { - if (bytes.Length < startIndex + Unsafe.SizeOf()) - ThrowIndexOutOfRangeException(); - Unsafe.As(ref bytes[startIndex]) = value; - } -#endif private static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); -#else - [StructLayout(LayoutKind.Explicit)] - private struct ConverterHelperDouble - { - [FieldOffset(0)] - public ulong Along; - - [FieldOffset(0)] - public double Adouble; - } - - [StructLayout(LayoutKind.Explicit)] - private struct ConverterHelperFloat - { - [FieldOffset(0)] - public int Aint; - - [FieldOffset(0)] - public float Afloat; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteLittleEndian(byte[] buffer, int offset, ulong data) - { -#if BIGENDIAN - buffer[offset + 7] = (byte)(data); - buffer[offset + 6] = (byte)(data >> 8); - buffer[offset + 5] = (byte)(data >> 16); - buffer[offset + 4] = (byte)(data >> 24); - buffer[offset + 3] = (byte)(data >> 32); - buffer[offset + 2] = (byte)(data >> 40); - buffer[offset + 1] = (byte)(data >> 48); - buffer[offset ] = (byte)(data >> 56); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); - buffer[offset + 2] = (byte)(data >> 16); - buffer[offset + 3] = (byte)(data >> 24); - buffer[offset + 4] = (byte)(data >> 32); - buffer[offset + 5] = (byte)(data >> 40); - buffer[offset + 6] = (byte)(data >> 48); - buffer[offset + 7] = (byte)(data >> 56); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteLittleEndian(byte[] buffer, int offset, int data) - { -#if BIGENDIAN - buffer[offset + 3] = (byte)(data); - buffer[offset + 2] = (byte)(data >> 8); - buffer[offset + 1] = (byte)(data >> 16); - buffer[offset ] = (byte)(data >> 24); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); - buffer[offset + 2] = (byte)(data >> 16); - buffer[offset + 3] = (byte)(data >> 24); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteLittleEndian(byte[] buffer, int offset, short data) - { -#if BIGENDIAN - buffer[offset + 1] = (byte)(data); - buffer[offset ] = (byte)(data >> 8); -#else - buffer[offset] = (byte)(data); - buffer[offset + 1] = (byte)(data >> 8); -#endif - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, double value) - { - ConverterHelperDouble ch = new ConverterHelperDouble { Adouble = value }; - WriteLittleEndian(bytes, startIndex, ch.Along); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, float value) - { - ConverterHelperFloat ch = new ConverterHelperFloat { Afloat = value }; - WriteLittleEndian(bytes, startIndex, ch.Aint); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, short value) - { - WriteLittleEndian(bytes, startIndex, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, ushort value) - { - WriteLittleEndian(bytes, startIndex, (short)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, int value) - { - WriteLittleEndian(bytes, startIndex, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, uint value) - { - WriteLittleEndian(bytes, startIndex, (int)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, long value) - { - WriteLittleEndian(bytes, startIndex, (ulong)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void GetBytes(byte[] bytes, int startIndex, ulong value) - { - WriteLittleEndian(bytes, startIndex, value); - } -#endif } } From 54eb7622f484de0b5f99e4db715197558b4825cd Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 20:24:30 +0300 Subject: [PATCH 175/200] API Standardization --- LiteNetLib/Utils/NetDataReader.cs | 64 ++++++------------------------- LiteNetLib/Utils/NetDataWriter.cs | 2 +- 2 files changed, 13 insertions(+), 53 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index ae17b689..42647bac 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -412,21 +412,17 @@ public string[] GetStringArray(int maxStringLength) } /// Reads the next from the buffer. - public byte GetByte() - { - EnsureAvailable(1); - return _data[_position++]; - } + public byte GetByte() => GetUnmanaged(); /// Reads the next from the buffer. - public sbyte GetSByte() => (sbyte)GetByte(); + public sbyte GetSByte() => GetUnmanaged(); /// Reads a value from the current position. /// if the byte is 1; otherwise, . - public bool GetBool() => GetByte() == 1; + public bool GetBool() => GetUnmanaged(); /// Reads a value as a 2-byte . - public char GetChar() => (char)GetUShort(); + public char GetChar() => GetUnmanaged(); /// Reads a value using unmanaged memory access. public ushort GetUShort() => GetUnmanaged(); @@ -716,16 +712,16 @@ public unsafe T GetUnmanaged() where T : unmanaged #region PeekMethods /// Reads the at the current position without advancing the . - public byte PeekByte() => _data[_position]; + public byte PeekByte() => PeekUnmanaged(); /// Reads the at the current position without advancing the . - public sbyte PeekSByte() => (sbyte)PeekByte(); + public sbyte PeekSByte() => PeekUnmanaged(); /// Reads the at the current position without advancing the . - public bool PeekBool() => PeekByte() == 1; + public bool PeekBool() => PeekUnmanaged(); /// Reads the at the current position without advancing the . - public char PeekChar() => (char)PeekUShort(); + public char PeekChar() => PeekUnmanaged(); /// Reads the at the current position without advancing the . public ushort PeekUShort() => PeekUnmanaged(); @@ -808,58 +804,22 @@ public unsafe T PeekUnmanaged() where T : unmanaged /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetByte(out byte result) - { - if (AvailableBytes >= 1) - { - result = GetByte(); - return true; - } - result = 0; - return false; - } + public bool TryGetByte(out byte result) => TryGetUnmanaged(out result); /// Attempts to read an without throwing an exception. /// The deserialized , or 0 if failed. /// if enough data was available; otherwise, . - public bool TryGetSByte(out sbyte result) - { - if (AvailableBytes >= 1) - { - result = GetSByte(); - return true; - } - result = 0; - return false; - } + public bool TryGetSByte(out sbyte result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or if failed. /// if enough data was available; otherwise, . - public bool TryGetBool(out bool result) - { - if (AvailableBytes >= 1) - { - result = GetBool(); - return true; - } - result = false; - return false; - } + public bool TryGetBool(out bool result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or '\0' if failed. /// if enough data was available; otherwise, . - public bool TryGetChar(out char result) - { - if (!TryGetUShort(out ushort uShortValue)) - { - result = '\0'; - return false; - } - result = (char)uShortValue; - return true; - } + public bool TryGetChar(out char result) => TryGetUnmanaged(out result); /// Attempts to read a without throwing an exception. /// The deserialized , or 0 if failed. diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 80eed775..542d94f9 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -374,7 +374,7 @@ public void PutBytesWithLength(byte[] data, int offset, ushort length) /// Serializes a value as a single . ///
    /// The value to write. - public void Put(bool value) => Put((byte)(value ? 1 : 0)); + public void Put(bool value) => PutUnmanaged(value); /// /// Serializes an prefixed with a 2-byte length. From bcdbef38655771b38edd30e5f968c2df36415f8a Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 21:57:22 +0300 Subject: [PATCH 176/200] Revert some changes --- LiteNetLib/Utils/NetDataReader.cs | 16 ++++++++++------ LiteNetLib/Utils/NetDataWriter.cs | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 42647bac..6ab35568 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -412,14 +412,18 @@ public string[] GetStringArray(int maxStringLength) } /// Reads the next from the buffer. - public byte GetByte() => GetUnmanaged(); + public byte GetByte() + { + EnsureAvailable(1); + return _data[_position++]; + } /// Reads the next from the buffer. - public sbyte GetSByte() => GetUnmanaged(); + public sbyte GetSByte() => (sbyte)GetByte(); /// Reads a value from the current position. /// if the byte is 1; otherwise, . - public bool GetBool() => GetUnmanaged(); + public bool GetBool() => GetByte() == 1; /// Reads a value as a 2-byte . public char GetChar() => GetUnmanaged(); @@ -712,13 +716,13 @@ public unsafe T GetUnmanaged() where T : unmanaged #region PeekMethods /// Reads the at the current position without advancing the . - public byte PeekByte() => PeekUnmanaged(); + public byte PeekByte() => _data[_position]; /// Reads the at the current position without advancing the . - public sbyte PeekSByte() => PeekUnmanaged(); + public sbyte PeekSByte() => (sbyte)PeekByte(); /// Reads the at the current position without advancing the . - public bool PeekBool() => PeekUnmanaged(); + public bool PeekBool() => PeekByte() == 1; /// Reads the at the current position without advancing the . public char PeekChar() => PeekUnmanaged(); diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 542d94f9..80eed775 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -374,7 +374,7 @@ public void PutBytesWithLength(byte[] data, int offset, ushort length) /// Serializes a value as a single . /// /// The value to write. - public void Put(bool value) => PutUnmanaged(value); + public void Put(bool value) => Put((byte)(value ? 1 : 0)); /// /// Serializes an prefixed with a 2-byte length. From bfe2282e796dc88ef0bcba3f2a358204b61ee04f Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 25 Mar 2026 20:26:42 +0100 Subject: [PATCH 177/200] Update docs --- LiteNetLib/BaseChannel.cs | 38 ++++++ LiteNetLib/ConnectionRequest.cs | 17 +++ LiteNetLib/INetEventListener.cs | 175 ++++++++++++++++++++++++- LiteNetLib/LiteNetManager.HashSet.cs | 2 +- LiteNetLib/LiteNetManager.cs | 8 ++ LiteNetLib/NatPunchModule.cs | 75 +++++++++++ LiteNetLib/NativeSocket.cs | 49 +++++++ LiteNetLib/NetConstants.cs | 49 ++++++- LiteNetLib/NetEvent.cs | 63 +++++++++ LiteNetLib/NetPacket.cs | 84 ++++++++++-- LiteNetLib/NetStatistics.cs | 54 ++++++++ LiteNetLib/NetUtils.cs | 22 ++++ LiteNetLib/Utils/FastBitConverter.cs | 10 ++ LiteNetLib/Utils/INetSerializable.cs | 15 +++ LiteNetLib/Utils/NetPacketProcessor.cs | 30 +++++ LiteNetLib/Utils/NtpRequest.cs | 24 ++++ LiteNetLib/Utils/Preserve.cs | 2 +- 17 files changed, 699 insertions(+), 18 deletions(-) diff --git a/LiteNetLib/BaseChannel.cs b/LiteNetLib/BaseChannel.cs index ce5ef10f..f8b6fd9c 100644 --- a/LiteNetLib/BaseChannel.cs +++ b/LiteNetLib/BaseChannel.cs @@ -3,17 +3,38 @@ namespace LiteNetLib { + /// + /// Base class for all communication channels (Reliable, Unreliable, Sequenced).
    + /// Handles the queuing and scheduling of outgoing packets. + ///
    internal abstract class BaseChannel { + /// + /// The peer associated with this channel. + /// protected readonly LiteNetPeer Peer; + /// + /// Queue containing packets waiting to be sent over the network. + /// protected readonly Queue OutgoingQueue = new Queue(NetConstants.DefaultWindowSize); private int _isAddedToPeerChannelSendQueue; + /// + /// Gets the number of packets currently residing in the outgoing queue. + /// public int PacketsInQueue => OutgoingQueue.Count; + /// + /// Initializes a new instance of the class. + /// + /// The peer that owns this channel. protected BaseChannel(LiteNetPeer peer) => Peer = peer; + /// + /// Adds a packet to the outgoing queue and notifies the peer to schedule a send update. + /// + /// The packet to be enqueued. public void AddToQueue(NetPacket packet) { lock (OutgoingQueue) @@ -23,12 +44,20 @@ public void AddToQueue(NetPacket packet) AddToPeerChannelSendQueue(); } + /// + /// Thread-safely marks this channel as having pending data and adds it to the peer's update list. + /// protected void AddToPeerChannelSendQueue() { if (Interlocked.CompareExchange(ref _isAddedToPeerChannelSendQueue, 1, 0) == 0) Peer.AddToReliableChannelSendQueue(this); } + /// + /// Attempts to send packets from the queue. If the queue becomes empty or throttled, + /// it resets the update flag. + /// + /// if there are still packets remaining to be sent in future updates. public bool SendAndCheckQueue() { bool hasPacketsToSend = SendNextPackets(); @@ -38,8 +67,17 @@ public bool SendAndCheckQueue() return hasPacketsToSend; } + /// + /// Abstract method to implement the specific logic for sending packets (e.g., windowing for reliable). + /// + /// if packets were sent and the channel should remain in the send queue. public abstract bool SendNextPackets(); + /// + /// Abstract method to handle an incoming packet received on this specific channel. + /// + /// The received packet. + /// if the packet was processed successfully. public abstract bool ProcessPacket(NetPacket packet); } } diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 3f770aa2..8fb15cf5 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -17,11 +17,17 @@ public class LiteConnectionRequest private readonly LiteNetManager _listener; private int _used; + /// + /// Data sent by the remote peer in the connection request. + /// public NetDataReader Data => InternalPacket.Data; internal ConnectionRequestResult Result { get; private set; } internal NetConnectRequestPacket InternalPacket; + /// + /// The remote endpoint (IP and Port) of the peer requesting the connection. + /// public readonly IPEndPoint RemoteEndPoint; internal void UpdateRequest(NetConnectRequestPacket connectRequest) @@ -47,6 +53,15 @@ internal LiteConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacke _listener = listener; } + /// + /// Accepts the connection if the first string in the matches the provided key. + /// + /// + /// This is a helper method for simple password/key validation. + /// If the key does not match or data is invalid, the connection is automatically rejected. + /// + /// The required string key to match. + /// A new if the key matches and connection is accepted; otherwise, null. public LiteNetPeer AcceptIfKey(string key) { if (!TryActivate()) @@ -164,8 +179,10 @@ internal ConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket re { } + /// public new NetPeer AcceptIfKey(string key) => (NetPeer)base.AcceptIfKey(key); + /// public new NetPeer Accept() => (NetPeer)base.Accept(); } } diff --git a/LiteNetLib/INetEventListener.cs b/LiteNetLib/INetEventListener.cs index bad9a074..17891c6e 100644 --- a/LiteNetLib/INetEventListener.cs +++ b/LiteNetLib/INetEventListener.cs @@ -224,37 +224,127 @@ void OnMessageDelivered(LiteNetPeer peer, object userData) { } ///
    public class EventBasedNetListener : INetEventListener { + /// + /// Delegate for the event that occurs when a new peer has successfully connected. + /// + /// The connected peer. public delegate void OnPeerConnected(NetPeer peer); + /// + /// Delegate for the event that occurs when a peer disconnects or the connection is lost. + /// + /// The disconnected peer. + /// Information regarding the reason and data associated with the disconnection. public delegate void OnPeerDisconnected(NetPeer peer, DisconnectInfo disconnectInfo); + /// + /// Delegate for the event that occurs when a network error is detected in the underlying socket. + /// + /// The endpoint associated with the error. + /// The specific socket error code. public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError); + /// + /// Delegate for the event that occurs when data is received from a connected peer. + /// + /// The peer that sent the data. + /// The reader containing the received payload. + /// The channel on which the data was received. + /// The delivery method used for this packet. public delegate void OnNetworkReceive(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod); + /// + /// Delegate for the event that occurs when a message is received from an unconnected endpoint. + /// + /// The endpoint that sent the message. + /// The reader containing the received payload. + /// The type of unconnected message (e.g., Discovery or UnconnectedData). public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); + /// + /// Delegate for the event that occurs when the round-trip time (RTT) to a peer is updated. + /// + /// The peer whose latency was updated. + /// The new latency value in milliseconds. public delegate void OnNetworkLatencyUpdate(NetPeer peer, int latency); + /// + /// Delegate for the event that occurs when a new connection request is received. + /// + /// The connection request object used to accept or reject the connection. public delegate void OnConnectionRequest(ConnectionRequest request); + /// + /// Delegate for the event that occurs when a reliable packet is successfully delivered or acknowledged. + /// + /// The peer that received the packet. + /// The custom user data that was attached to the sent packet. public delegate void OnDeliveryEvent(NetPeer peer, object userData); + /// + /// Delegate for the event that occurs when an NTP response is received from a time server. + /// + /// The NTP packet containing time information. public delegate void OnNtpResponseEvent(NtpPacket packet); + /// + /// Delegate for the event that occurs when a peer's remote address changes (roaming). + /// + /// The peer whose address changed. + /// The previous IP endpoint of the peer. public delegate void OnPeerAddressChangedEvent(NetPeer peer, IPEndPoint previousAddress); + /// + /// Occurs when a new peer has successfully connected. + /// public event OnPeerConnected PeerConnectedEvent; + /// + /// Occurs when a peer disconnects or the connection is lost. + /// public event OnPeerDisconnected PeerDisconnectedEvent; + /// + /// Occurs when a network error is detected in the underlying socket. + /// public event OnNetworkError NetworkErrorEvent; + /// + /// Occurs when data is received from a connected peer. + /// public event OnNetworkReceive NetworkReceiveEvent; + /// + /// Occurs when a message is received from an unconnected endpoint. + /// public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; + /// + /// Occurs when the round-trip time (RTT) to a peer is updated. + /// public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; + /// + /// Occurs when a new connection request is received. + /// public event OnConnectionRequest ConnectionRequestEvent; + /// + /// Occurs when a reliable packet is successfully delivered or acknowledged. + /// public event OnDeliveryEvent DeliveryEvent; + /// + /// Occurs when an NTP response is received. + /// public event OnNtpResponseEvent NtpResponseEvent; + /// + /// Occurs when a peer's remote address changes. + /// public event OnPeerAddressChangedEvent PeerAddressChangedEvent; - public void ClearPeerConnectedEvent() => PeerConnectedEvent = null; + /// Clears all subscribers from . + public void ClearPeerConnectedEvent() => PeerConnectedEvent = null; + /// Clears all subscribers from . public void ClearPeerDisconnectedEvent() => PeerDisconnectedEvent = null; + /// Clears all subscribers from . public void ClearNetworkErrorEvent() => NetworkErrorEvent = null; + /// Clears all subscribers from . public void ClearNetworkReceiveEvent() => NetworkReceiveEvent = null; + /// Clears all subscribers from . public void ClearNetworkReceiveUnconnectedEvent() => NetworkReceiveUnconnectedEvent = null; + /// Clears all subscribers from . public void ClearNetworkLatencyUpdateEvent() => NetworkLatencyUpdateEvent = null; + /// Clears all subscribers from . public void ClearConnectionRequestEvent() => ConnectionRequestEvent = null; + /// Clears all subscribers from . public void ClearDeliveryEvent() => DeliveryEvent = null; + /// Clears all subscribers from . public void ClearNtpResponseEvent() => NtpResponseEvent = null; + /// Clears all subscribers from . public void ClearPeerAddressChangedEvent() => PeerAddressChangedEvent = null; void INetEventListener.OnPeerConnected(NetPeer peer) => @@ -293,34 +383,115 @@ void INetEventListener.OnPeerAddressChanged(NetPeer peer, IPEndPoint previousAdd ///
    public class EventBasedLiteNetListener : ILiteNetEventListener { + /// + /// Delegate for the event that occurs when a new peer has successfully connected. + /// + /// The connected peer. public delegate void OnPeerConnected(LiteNetPeer peer); + /// + /// Delegate for the event that occurs when a peer disconnects or the connection is lost. + /// + /// The disconnected peer. + /// Information regarding the reason and data associated with the disconnection. public delegate void OnPeerDisconnected(LiteNetPeer peer, DisconnectInfo disconnectInfo); + /// + /// Delegate for the event that occurs when a network error is detected in the underlying socket. + /// + /// The endpoint associated with the error. + /// The specific socket error code. public delegate void OnNetworkError(IPEndPoint endPoint, SocketError socketError); + /// + /// Delegate for the event that occurs when data is received from a connected peer. + /// + /// The peer that sent the data. + /// The reader containing the received payload. + /// The delivery method used for this packet. public delegate void OnNetworkReceive(LiteNetPeer peer, NetPacketReader reader, DeliveryMethod deliveryMethod); + /// + /// Delegate for the event that occurs when a message is received from an unconnected endpoint. + /// + /// The endpoint that sent the message. + /// The reader containing the received payload. + /// The type of unconnected message (e.g., Discovery or UnconnectedData). public delegate void OnNetworkReceiveUnconnected(IPEndPoint remoteEndPoint, NetPacketReader reader, UnconnectedMessageType messageType); + /// + /// Delegate for the event that occurs when the round-trip time (RTT) to a peer is updated. + /// + /// The peer whose latency was updated. + /// The new latency value in milliseconds. public delegate void OnNetworkLatencyUpdate(LiteNetPeer peer, int latency); + /// + /// Delegate for the event that occurs when a new connection request is received. + /// + /// The connection request object used to accept or reject the connection. public delegate void OnConnectionRequest(LiteConnectionRequest request); + /// + /// Delegate for the event that occurs when a reliable packet is successfully delivered or acknowledged. + /// + /// The peer that received the packet. + /// The custom user data that was attached to the sent packet. public delegate void OnDeliveryEvent(LiteNetPeer peer, object userData); + /// + /// Delegate for the event that occurs when a peer's remote address changes (roaming). + /// + /// The peer whose address changed. + /// The previous IP endpoint of the peer. public delegate void OnPeerAddressChangedEvent(LiteNetPeer peer, IPEndPoint previousAddress); + /// + /// Occurs when a new peer has successfully connected. + /// public event OnPeerConnected PeerConnectedEvent; + /// + /// Occurs when a peer disconnects or the connection is lost. + /// public event OnPeerDisconnected PeerDisconnectedEvent; + /// + /// Occurs when a network error is detected in the underlying socket. + /// public event OnNetworkError NetworkErrorEvent; + /// + /// Occurs when data is received from a connected peer. + /// public event OnNetworkReceive NetworkReceiveEvent; + /// + /// Occurs when a message is received from an unconnected endpoint. + /// public event OnNetworkReceiveUnconnected NetworkReceiveUnconnectedEvent; + /// + /// Occurs when the round-trip time (RTT) to a peer is updated. + /// public event OnNetworkLatencyUpdate NetworkLatencyUpdateEvent; + /// + /// Occurs when a new connection request is received. + /// public event OnConnectionRequest ConnectionRequestEvent; + /// + /// Occurs when a reliable packet is successfully delivered or acknowledged. + /// public event OnDeliveryEvent DeliveryEvent; + /// + /// Occurs when a peer's remote address changes. + /// public event OnPeerAddressChangedEvent PeerAddressChangedEvent; - public void ClearPeerConnectedEvent() => PeerConnectedEvent = null; + /// Clears all subscribers from . + public void ClearPeerConnectedEvent() => PeerConnectedEvent = null; + /// Clears all subscribers from . public void ClearPeerDisconnectedEvent() => PeerDisconnectedEvent = null; + /// Clears all subscribers from . public void ClearNetworkErrorEvent() => NetworkErrorEvent = null; + /// Clears all subscribers from . public void ClearNetworkReceiveEvent() => NetworkReceiveEvent = null; + /// Clears all subscribers from . public void ClearNetworkReceiveUnconnectedEvent() => NetworkReceiveUnconnectedEvent = null; + /// Clears all subscribers from . public void ClearNetworkLatencyUpdateEvent() => NetworkLatencyUpdateEvent = null; + /// Clears all subscribers from . public void ClearConnectionRequestEvent() => ConnectionRequestEvent = null; + /// Clears all subscribers from . public void ClearDeliveryEvent() => DeliveryEvent = null; + /// Clears all subscribers from . public void ClearPeerAddressChangedEvent() => PeerAddressChangedEvent = null; void ILiteNetEventListener.OnPeerConnected(LiteNetPeer peer) => diff --git a/LiteNetLib/LiteNetManager.HashSet.cs b/LiteNetLib/LiteNetManager.HashSet.cs index 9d5fe2e3..11fdd114 100644 --- a/LiteNetLib/LiteNetManager.HashSet.cs +++ b/LiteNetLib/LiteNetManager.HashSet.cs @@ -118,7 +118,7 @@ public LiteNetPeer GetPeerById(int id) ///
    /// id of peer /// resulting peer - /// True if peer with id exist, otherwise false + /// if peer with id exist; otherwise public bool TryGetPeerById(int id, out LiteNetPeer peer) { peer = GetPeerById(id); diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 194b0b05..5769b888 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -269,6 +269,14 @@ private struct OutboundDelayedPacket ///
    public int ConnectedPeersCount => (int)Interlocked.Read(ref _connectedPeersCount); + /// + /// Gets the additional size in bytes required by the active . + /// + /// + /// This value is used by to calculate the available MTU for user data.
    + /// If a packet layer is active (e.g., for encryption or CRC), this returns the overhead added to every packet. + /// Returns 0 if no packet layer is assigned. + ///
    public int ExtraPacketSizeForLayer => _extraPacketLayer?.ExtraPacketSizeForLayer ?? 0; /// diff --git a/LiteNetLib/NatPunchModule.cs b/LiteNetLib/NatPunchModule.cs index a124eb86..94251a86 100644 --- a/LiteNetLib/NatPunchModule.cs +++ b/LiteNetLib/NatPunchModule.cs @@ -6,24 +6,66 @@ namespace LiteNetLib { + /// + /// Specifies the type of network address discovered during NAT punchthrough. + /// public enum NatAddressType { + /// + /// Address within the local area network (LAN). + /// Internal, + /// + /// Publicly accessible address on the wide area network (WAN). + /// External } + /// + /// Interface for handling events related to NAT punchthrough and introduction. + /// public interface INatPunchListener { + /// + /// Called when a NAT introduction request is received from the mediator server. + /// + /// The local endpoint of the client requesting connection. + /// The remote endpoint of the client requesting connection. + /// Custom data token associated with the request. void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token); + + /// + /// Called when NAT punchthrough is successful and a direct connection can be established. + /// + /// The resolved endpoint of the remote peer. + /// The type of address (Internal or External) that succeeded. + /// Custom data token associated with the request. void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token); } + /// + /// An implementation of that maps callbacks to events. + /// public class EventBasedNatPunchListener : INatPunchListener { + /// + /// Delegate for NAT introduction request events. + /// public delegate void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token); + + /// + /// Delegate for NAT introduction success events. + /// public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token); + /// + /// Event triggered when a NAT introduction request is received. + /// public event OnNatIntroductionRequest NatIntroductionRequest; + + /// + /// Event triggered when NAT punchthrough is successfully completed. + /// public event OnNatIntroductionSuccess NatIntroductionSuccess; void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token) @@ -84,6 +126,9 @@ class NatPunchPacket private readonly NetDataWriter _cacheWriter = new NetDataWriter(); private readonly NetPacketProcessor _netPacketProcessor = new NetPacketProcessor(MaxTokenLength); private INatPunchListener _natPunchListener; + /// + /// Maximum allowed length for the NAT introduction token string. + /// public const int MaxTokenLength = 256; /// @@ -108,6 +153,10 @@ internal void ProcessMessage(IPEndPoint senderEndPoint, NetPacket packet) } } + /// + /// Initializes the NAT punch module with a listener to handle punchthrough events. + /// + /// The listener implementation that will receive NAT events. public void Init(INatPunchListener listener) { _natPunchListener = listener; @@ -125,6 +174,15 @@ private void Send< _socket.SendRaw(_cacheWriter.Data, 0, _cacheWriter.Length, target); } + /// + /// Sends NAT introduction packets to both the host and the client to facilitate punchthrough. + /// This is typically called by a mediator (Master Server). + /// + /// Internal (LAN) endpoint of the host. + /// External (WAN) endpoint of the host. + /// Internal (LAN) endpoint of the client. + /// External (WAN) endpoint of the client. + /// Custom token or data to include in the introduction. public void NatIntroduce( IPEndPoint hostInternal, IPEndPoint hostExternal, @@ -148,6 +206,12 @@ public void NatIntroduce( Send(req, hostExternal); } + /// + /// Triggers queued NAT punchthrough events (Success or Request) on the provided . + /// + /// + /// This should be called from the main thread if is . + /// public void PollEvents() { if (UnsyncedEvents) @@ -170,11 +234,22 @@ public void PollEvents() } } + /// + /// Sends a request to the Master Server to introduce this peer to another peer. + /// + /// The hostname or IP of the Master Server. + /// The port of the Master Server. + /// Custom token to identify the connection or room. public void SendNatIntroduceRequest(string host, int port, string additionalInfo) { SendNatIntroduceRequest(NetUtils.MakeEndPoint(host, port), additionalInfo); } + /// + /// Sends a request to the Master Server to introduce this peer to another peer. + /// + /// The endpoint of the Master Server. + /// Custom token to identify the connection or room. public void SendNatIntroduceRequest(IPEndPoint masterServerEndPoint, string additionalInfo) { //prepare outgoing data diff --git a/LiteNetLib/NativeSocket.cs b/LiteNetLib/NativeSocket.cs index 5bac9e59..84ecedc4 100644 --- a/LiteNetLib/NativeSocket.cs +++ b/LiteNetLib/NativeSocket.cs @@ -55,12 +55,30 @@ internal static extern int sendto( [In] int socketAddressSize); } + /// + /// Indicates whether the native socket optimizations are supported on the current platform. + /// public static readonly bool IsSupported = false; + /// + /// Indicates whether the current environment requires Unix-style native socket calls. + /// public static readonly bool UnixMode = false; + /// + /// The size of the native sockaddr_in structure for IPv4. + /// public const int IPv4AddrSize = 16; + /// + /// The size of the native sockaddr_in6 structure for IPv6. + /// public const int IPv6AddrSize = 28; + /// + /// Native Address Family constant for IPv4 (AF_INET). + /// public const int AF_INET = 2; + /// + /// Native Address Family constant for IPv6 (AF_INET6). + /// public const int AF_INET6 = 10; private static readonly Dictionary NativeErrorToSocketError = new Dictionary @@ -122,6 +140,15 @@ static NativeSocket() } } + /// + /// Receives a datagram from the specified socket handle using native OS calls. + /// + /// The OS handle for the socket. + /// A pinned byte array to receive the data. + /// The number of s to receive. + /// A pinned byte array to store the source address (sockaddr). + /// The size of the structure. + /// The number of s received, or a negative value on error. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int RecvFrom( IntPtr socketHandle, @@ -133,6 +160,15 @@ public static int RecvFrom( ? UnixSock.recvfrom(socketHandle, pinnedBuffer, len, 0, socketAddress, ref socketAddressSize) : WinSock.recvfrom(socketHandle, pinnedBuffer, len, 0, socketAddress, ref socketAddressSize); + /// + /// Sends a datagram to the specified socket handle using native OS calls. + /// + /// The OS handle for the socket. + /// A pointer to the pinned memory containing data to send. + /// The number of s to send. + /// A pinned byte array containing the destination address (sockaddr). + /// The size of the structure. + /// The number of s sent, or a negative value on error. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe int SendTo( IntPtr socketHandle, @@ -144,6 +180,10 @@ public static unsafe int SendTo( ? UnixSock.sendto(socketHandle, pinnedBuffer, len, 0, socketAddress, socketAddressSize) : WinSock.sendto(socketHandle, pinnedBuffer, len, 0, socketAddress, socketAddressSize); + /// + /// Retrieves the last OS-specific socket error and translates it to . + /// + /// The translated . public static SocketError GetSocketError() { int error = Marshal.GetLastWin32Error(); @@ -154,6 +194,10 @@ public static SocketError GetSocketError() return (SocketError)error; } + /// + /// Retrieves the last OS-specific socket error and encapsulates it in a . + /// + /// A representing the last native error. public static SocketException GetSocketException() { int error = Marshal.GetLastWin32Error(); @@ -164,6 +208,11 @@ public static SocketException GetSocketException() return new SocketException(error); } + /// + /// Converts the of an endpoint to the corresponding native constant. + /// + /// The endpoint to evaluate. + /// The native address family identifier. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static short GetNativeAddressFamily(IPEndPoint remoteEndPoint) => UnixMode diff --git a/LiteNetLib/NetConstants.cs b/LiteNetLib/NetConstants.cs index 31495d10..75dbea85 100644 --- a/LiteNetLib/NetConstants.cs +++ b/LiteNetLib/NetConstants.cs @@ -37,16 +37,46 @@ public enum DeliveryMethod : byte /// public static class NetConstants { - //can be tuned + /// + /// Default window size for reliable channels (number of packets). + /// public const int DefaultWindowSize = 64; - public const int SocketBufferSize = 1024 * 1024; //1mb + /// + /// Size of the underlying UDP socket receive and send buffers in bytes.
    + /// Default is 1MB. + ///
    + public const int SocketBufferSize = 1024 * 1024; + /// + /// Time To Live (TTL) for the UDP packets. + /// public const int SocketTTL = 255; + /// + /// Size of the base packet header (PacketProperty) in s. + /// public const int HeaderSize = 1; + /// + /// Size of the header for sequenced or reliable messages in s.
    + /// Includes , Sequence, and ChannelId. + ///
    public const int ChanneledHeaderSize = 4; + /// + /// Additional header size required for fragmented packets in s.
    + /// Includes FragmentId, FragmentPart, and FragmentsTotal. + ///
    public const int FragmentHeaderSize = 6; + /// + /// Total header size for a fragmented channeled packet in s.
    + /// Combines and . + ///
    public const int FragmentedHeaderTotalSize = ChanneledHeaderSize + FragmentHeaderSize; + /// + /// Maximum possible sequence number before wrapping back to zero. + /// public const ushort MaxSequence = 32768; + /// + /// Half of the , used for sequence comparison and wrap-around logic. + /// public const ushort HalfMaxSequence = MaxSequence / 2; //protocol @@ -67,12 +97,23 @@ public static class NetConstants 1500 - MaxUdpHeaderSize //Ethernet II (RFC 1191) }; - //Max possible single packet size + /// + /// The starting Maximum Transmission Unit (MTU) used for new connections before path MTU discovery. + /// public static readonly int InitialMtu = PossibleMtu[0]; + /// + /// Maximum possible packet size allowed by the library based on the largest supported MTU. + /// public static readonly int MaxPacketSize = PossibleMtu[PossibleMtu.Length - 1]; + /// + /// Maximum payload size for a single unreliable packet in s.
    + /// Calculated as - . + ///
    public static readonly int MaxUnreliableDataSize = MaxPacketSize - HeaderSize; - //peer specific + /// + /// Maximum number of simultaneous connection attempts (pending connections) allowed per peer. + /// public const byte MaxConnectionNumber = 4; } } diff --git a/LiteNetLib/NetEvent.cs b/LiteNetLib/NetEvent.cs index b54f60aa..7b701e69 100644 --- a/LiteNetLib/NetEvent.cs +++ b/LiteNetLib/NetEvent.cs @@ -8,34 +8,97 @@ namespace LiteNetLib ///
    public sealed class NetEvent { + /// + /// Reference to the next event in the pool or event queue. + /// public NetEvent Next; + /// + /// Specifies the category of the network event. + /// public enum EType { + /// New peer connected. Connect, + /// Peer disconnected. Disconnect, + /// Data received from a connected peer. Receive, + /// Unconnected message received. ReceiveUnconnected, + /// Socket or internal protocol error occurred. Error, + /// Round-trip time (RTT) for a peer has been updated. ConnectionLatencyUpdated, + /// Broadcast message received. Broadcast, + /// Incoming connection request from a new peer. ConnectionRequest, + /// Reliable message was successfully delivered to the remote peer. MessageDelivered, + /// The IP address or port of an existing peer has changed (e.g., roaming). PeerAddressChanged } + + /// + /// The type of network event that occurred. + /// public EType Type; + /// + /// The peer associated with this event. for unconnected events. + /// public LiteNetPeer Peer; + + /// + /// The remote endpoint (IP and Port) from which the event originated. + /// public IPEndPoint RemoteEndPoint; + + /// + /// Optional user data associated with a connection request or disconnect. + /// public object UserData; + + /// + /// The updated latency value in milliseconds. Only valid when is . + /// public int Latency; + + /// + /// The specific socket error. Only valid when is . + /// public SocketError ErrorCode; + + /// + /// The reason for a peer's disconnection. Only valid when is . + /// public DisconnectReason DisconnectReason; + + /// + /// Information about an incoming connection. Only valid when is . + /// public LiteConnectionRequest ConnectionRequest; + + /// + /// The delivery method used for the received packet. Only valid when is . + /// public DeliveryMethod DeliveryMethod; + + /// + /// The channel on which the packet was received. + /// public byte ChannelNumber; + + /// + /// A reader for accessing the payload of received data, broadcast, or unconnected messages. + /// public readonly NetPacketReader DataReader; + /// + /// Initializes a new instance of the class. + /// + /// The that owns the packet pool and buffers for this event. public NetEvent(LiteNetManager manager) { DataReader = new NetPacketReader(manager, this); diff --git a/LiteNetLib/NetPacket.cs b/LiteNetLib/NetPacket.cs index 495e6ad9..e22541ff 100644 --- a/LiteNetLib/NetPacket.cs +++ b/LiteNetLib/NetPacket.cs @@ -66,81 +66,145 @@ static NetPacket() } } - //Header + /// + /// Gets or sets the packet property (type). + /// Stored in the first 5 bits of the first byte (0x1F mask). + /// public PacketProperty Property { get => (PacketProperty)(RawData[0] & 0x1F); set => RawData[0] = (byte)((RawData[0] & 0xE0) | (byte)value); } + /// + /// Gets or sets the connection number used to distinguish between multiple connections from the same endpoint.
    + /// Stored in bits 6 and 7 of the first byte (0x60 mask). + ///
    public byte ConnectionNumber { get => (byte)((RawData[0] & 0x60) >> 5); - set => RawData[0] = (byte) ((RawData[0] & 0x9F) | (value << 5)); + set => RawData[0] = (byte)((RawData[0] & 0x9F) | (value << 5)); } + /// + /// Gets or sets the sequence number of the packet. + /// Located at offset 1 in . + /// public ushort Sequence { get => BitConverter.ToUInt16(RawData, 1); set => FastBitConverter.GetBytes(RawData, 1, value); } + /// + /// Returns if the fragmentation bit (the highest bit of the first byte) is set. + /// public bool IsFragmented => (RawData[0] & 0x80) != 0; - public void MarkFragmented() => RawData[0] |= 0x80; //set first bit + /// + /// Sets the fragmentation bit (0x80) in the packet header. + /// + public void MarkFragmented() => RawData[0] |= 0x80; + /// + /// Gets or sets the channel identifier. + /// Located at offset 3 in . + /// public byte ChannelId { get => RawData[3]; set => RawData[3] = value; } + /// + /// Gets or sets the unique identifier for a fragmented message. + /// Located at offset 4 in . + /// public ushort FragmentId { get => BitConverter.ToUInt16(RawData, 4); set => FastBitConverter.GetBytes(RawData, 4, value); } + /// + /// Gets or sets the index of the current fragment part. + /// Located at offset 6 in . + /// public ushort FragmentPart { get => BitConverter.ToUInt16(RawData, 6); set => FastBitConverter.GetBytes(RawData, 6, value); } + /// + /// Gets or sets the total number of fragments in the message. + /// Located at offset 8 in . + /// public ushort FragmentsTotal { get => BitConverter.ToUInt16(RawData, 8); set => FastBitConverter.GetBytes(RawData, 8, value); } - //Data + /// + /// The raw array containing the packet header and payload. + /// public byte[] RawData; + + /// + /// The actual size of the data in , including headers. + /// public int Size; - //Delivery + /// + /// Custom user data associated with this packet. Used for delivery notifications. + /// public object UserData; - //Pool node + /// + /// Reference to the next packet in the NetPacketPool. + /// public NetPacket Next; + /// + /// Initializes a new instance of the class with a specific buffer size. + /// + /// Total size of the packet including headers. public NetPacket(int size) { RawData = new byte[size]; Size = size; } - public NetPacket(PacketProperty property, int size) + /// + /// Initializes a new instance of the class, calculating the required size based on the property. + /// + /// The type of packet to create. + /// Size of the user data payload. + public NetPacket(PacketProperty property, int payloadSize) { - size += GetHeaderSize(property); - RawData = new byte[size]; + int totalSize = payloadSize + GetHeaderSize(property); + RawData = new byte[totalSize]; Property = property; - Size = size; + Size = totalSize; } + /// + /// Gets the fixed header size for a specific . + /// + /// The packet type. + /// Header size in bytes. public static int GetHeaderSize(PacketProperty property) => HeaderSizes[(int)property]; + /// + /// Gets the header size of the current packet based on its property bits. + /// public int HeaderSize => HeaderSizes[RawData[0] & 0x1F]; + /// + /// Performs a basic sanity check on the packet header and size. + /// + /// True if the packet property is valid and the size is sufficient for the headers. public bool Verify() { byte property = (byte)(RawData[0] & 0x1F); diff --git a/LiteNetLib/NetStatistics.cs b/LiteNetLib/NetStatistics.cs index 5b3d8fd2..e2d0304c 100644 --- a/LiteNetLib/NetStatistics.cs +++ b/LiteNetLib/NetStatistics.cs @@ -2,6 +2,9 @@ namespace LiteNetLib { + /// + /// Thread-safe counter for network statistics including sent/received packets, bytes, and packet loss. + /// public sealed class NetStatistics { private long _packetsSent; @@ -10,12 +13,35 @@ public sealed class NetStatistics private long _bytesReceived; private long _packetLoss; + /// + /// Total number of packets sent. + /// public long PacketsSent => Interlocked.Read(ref _packetsSent); + + /// + /// Total number of packets received. + /// public long PacketsReceived => Interlocked.Read(ref _packetsReceived); + + /// + /// Total number of bytes sent. + /// public long BytesSent => Interlocked.Read(ref _bytesSent); + + /// + /// Total number of bytes received. + /// public long BytesReceived => Interlocked.Read(ref _bytesReceived); + + /// + /// Total number of packets lost during transmission. + /// public long PacketLoss => Interlocked.Read(ref _packetLoss); + /// + /// Percentage of sent packets that were lost. + /// Calculated as (PacketLoss * 100) / PacketsSent. + /// public long PacketLossPercent { get @@ -26,6 +52,9 @@ public long PacketLossPercent } } + /// + /// Resets all statistical counters to zero. + /// public void Reset() { Interlocked.Exchange(ref _packetsSent, 0); @@ -35,24 +64,49 @@ public void Reset() Interlocked.Exchange(ref _packetLoss, 0); } + /// + /// Increments the count of sent packets by one. + /// public void IncrementPacketsSent() => Interlocked.Increment(ref _packetsSent); + /// + /// Increments the count of received packets by one. + /// public void IncrementPacketsReceived() => Interlocked.Increment(ref _packetsReceived); + /// + /// Adds a specific amount to the total bytes sent. + /// + /// Number of bytes to add. public void AddBytesSent(long bytesSent) => Interlocked.Add(ref _bytesSent, bytesSent); + /// + /// Adds a specific amount to the total bytes received. + /// + /// Number of bytes to add. public void AddBytesReceived(long bytesReceived) => Interlocked.Add(ref _bytesReceived, bytesReceived); + /// + /// Increments the count of lost packets by one. + /// public void IncrementPacketLoss() => Interlocked.Increment(ref _packetLoss); + /// + /// Adds a specific amount to the total packet loss count. + /// + /// Number of lost packets to add. public void AddPacketLoss(long packetLoss) => Interlocked.Add(ref _packetLoss, packetLoss); + /// + /// Returns a string representation of the current network statistics. + /// + /// A formatted string containing bytes received/sent, packets received/sent, and loss information. public override string ToString() { return diff --git a/LiteNetLib/NetUtils.cs b/LiteNetLib/NetUtils.cs index 9d9ab733..593c2f2a 100644 --- a/LiteNetLib/NetUtils.cs +++ b/LiteNetLib/NetUtils.cs @@ -25,9 +25,25 @@ public static class NetUtils { private static readonly NetworkSorter NetworkSorter = new NetworkSorter(); + /// + /// Creates an from a host string and a port. + /// + /// The host name or IP address string to resolve. + /// The port number for the endpoint. + /// A new instance. public static IPEndPoint MakeEndPoint(string hostStr, int port) => new IPEndPoint(ResolveAddress(hostStr), port); + /// + /// Resolves a host string into an . + /// + /// + /// This method handles "localhost" specifically, attempts to parse the string as a direct IP, + /// and falls back to DNS resolution. It prioritizes IPv6 if is enabled. + /// + /// The host name or IP address string (e.g., "127.0.0.1", "localhost", or "google.com"). + /// The resolved . + /// Thrown when the address cannot be resolved or is invalid. public static IPAddress ResolveAddress(string hostStr) { if(hostStr == "localhost") @@ -46,6 +62,12 @@ public static IPAddress ResolveAddress(string hostStr) return ipAddress; } + /// + /// Resolves a host string using DNS for a specific . + /// + /// The host name to resolve via DNS. + /// The preferred address family (e.g., or ). + /// The first matching the family, or if no match is found. public static IPAddress ResolveAddress(string hostStr, AddressFamily addressFamily) { IPAddress[] addresses = Dns.GetHostEntry(hostStr).AddressList; diff --git a/LiteNetLib/Utils/FastBitConverter.cs b/LiteNetLib/Utils/FastBitConverter.cs index 1a6c3287..202cf134 100644 --- a/LiteNetLib/Utils/FastBitConverter.cs +++ b/LiteNetLib/Utils/FastBitConverter.cs @@ -8,6 +8,16 @@ namespace LiteNetLib.Utils { public static class FastBitConverter { + /// + /// Converts a value of type into a byte array starting at the specified index. + /// + /// The type of the value to convert. Must be an unmanaged/blittable type. + /// The destination byte array. + /// The zero-based index in at which to begin writing. + /// The value to be converted and written. + /// + /// Thrown when the array is too small to contain the value at the given . + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe void GetBytes(byte[] bytes, int startIndex, T value) where T : unmanaged { diff --git a/LiteNetLib/Utils/INetSerializable.cs b/LiteNetLib/Utils/INetSerializable.cs index 92f14bee..423e0468 100644 --- a/LiteNetLib/Utils/INetSerializable.cs +++ b/LiteNetLib/Utils/INetSerializable.cs @@ -1,8 +1,23 @@ namespace LiteNetLib.Utils { + /// + /// Interface for implementing custom data serialization for network transmission. + /// + /// + /// This is the most efficient way to send complex objects as it avoids reflection. + /// public interface INetSerializable { + /// + /// Writes the object data into the provided . + /// + /// The writer to pack data into. void Serialize(NetDataWriter writer); + + /// + /// Reads the object data from the provided . + /// + /// The reader to extract data from. void Deserialize(NetDataReader reader); } } diff --git a/LiteNetLib/Utils/NetPacketProcessor.cs b/LiteNetLib/Utils/NetPacketProcessor.cs index c18683e5..e3d8d981 100644 --- a/LiteNetLib/Utils/NetPacketProcessor.cs +++ b/LiteNetLib/Utils/NetPacketProcessor.cs @@ -229,6 +229,13 @@ public void SubscribeReusable< }; } + /// + /// Registers a callback for a packet type that implements , using a custom constructor and supporting user data. + /// + /// The type of the packet. Must implement . + /// The type of the user data (typically ). + /// The delegate to be executed when the packet is received. + /// A function that returns a new instance of . public void SubscribeNetSerializable( Action onReceive, Func packetConstructor) where T : INetSerializable @@ -241,6 +248,12 @@ public void SubscribeNetSerializable( }; } + /// + /// Registers a callback for a packet type that implements , using a custom constructor. + /// + /// The type of the packet. Must implement . + /// The delegate to be executed when the packet is received. + /// A function that returns a new instance of . public void SubscribeNetSerializable( Action onReceive, Func packetConstructor) where T : INetSerializable @@ -253,6 +266,15 @@ public void SubscribeNetSerializable( }; } + /// + /// Registers a callback for a packet type that implements and has a parameterless constructor, supporting user data. + /// + /// + /// To reduce allocations, this method uses a single internal reference to for deserialization. + /// + /// The type of the packet. Must implement and have a () constraint. + /// The type of the user data (typically ). + /// The delegate to be executed when the packet is received. public void SubscribeNetSerializable( Action onReceive) where T : INetSerializable, new() { @@ -264,6 +286,14 @@ public void SubscribeNetSerializable( }; } + /// + /// Registers a callback for a packet type that implements and has a parameterless constructor. + /// + /// + /// To reduce allocations, this method uses a single internal reference to for deserialization. + /// + /// The type of the packet. Must implement and have a () constraint. + /// The delegate to be executed when the packet is received. public void SubscribeNetSerializable( Action onReceive) where T : INetSerializable, new() { diff --git a/LiteNetLib/Utils/NtpRequest.cs b/LiteNetLib/Utils/NtpRequest.cs index ca83c8d0..dc0c2aed 100644 --- a/LiteNetLib/Utils/NtpRequest.cs +++ b/LiteNetLib/Utils/NtpRequest.cs @@ -3,22 +3,46 @@ namespace LiteNetLib.Utils { + /// + /// Represents an active NTP (Network Time Protocol) query to a remote time server. + /// Handles retransmission and lifetime management of the request. + /// internal sealed class NtpRequest { private const int ResendTimer = 1000; private const int KillTimer = 10000; + /// + /// Standard UDP port used by NTP servers. + /// public const int DefaultPort = 123; private readonly IPEndPoint _ntpEndPoint; private float _resendTime = ResendTimer; private float _killTime = 0; + /// + /// Initializes a new instance of the class for a specific server. + /// + /// The IP endpoint of the NTP server. public NtpRequest(IPEndPoint endPoint) { _ntpEndPoint = endPoint; } + /// + /// Gets a value indicating whether the request has exceeded its maximum lifetime and should be removed. + /// public bool NeedToKill => _killTime >= KillTimer; + /// + /// Attempts to send an NTP query packet to the remote endpoint. + /// + /// + /// The packet is only sent if the internal retransmission timer has elapsed. + /// Updates internal timers for both retransmission and total lifetime. + /// + /// The underlying socket used to send the datagram. + /// The amount of time elapsed since the last update/call, in seconds. + /// if the packet was successfully transmitted; otherwise, . public bool Send(Socket socket, float time) { _resendTime += time; diff --git a/LiteNetLib/Utils/Preserve.cs b/LiteNetLib/Utils/Preserve.cs index b73e1b90..057798b9 100644 --- a/LiteNetLib/Utils/Preserve.cs +++ b/LiteNetLib/Utils/Preserve.cs @@ -3,7 +3,7 @@ namespace LiteNetLib.Utils { /// - /// PreserveAttribute prevents byte code stripping from removing a class, method, field, or property. + /// PreserveAttribute prevents byte code stripping from removing a class, method, field, or property. /// [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)] public class PreserveAttribute : Attribute From f20ced73612f1a496f5566565670e1769df5584e Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 22:28:51 +0300 Subject: [PATCH 178/200] ResizeIfNeed now throws error if need resize but !_autoResize --- LiteNetLib/Utils/NetDataWriter.cs | 89 +++++++++++++++++-------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 80eed775..4a508b44 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -125,36 +125,56 @@ public static NetDataWriter FromString(string value) } /// - /// Ensures the internal buffer is at least . + /// Ensures that the internal buffer is at least bytes long. /// /// The required minimum size of the buffer. - /// - /// If an allocation is necessary, the buffer grows to either - /// or doubles its current size, whichever is larger. - /// + /// + /// Thrown when exceeds the current buffer capacity + /// and automatic resizing is disabled. + /// + /// + /// Thrown when is negative. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ResizeIfNeed(int newSize) { - if (_data.Length < newSize) - { - Array.Resize(ref _data, Math.Max(newSize, _data.Length * 2)); - } + if (newSize < 0) + ThrowCapacityExceeded(newSize); + + if (_data.Length >= newSize) + return; + + if (!_autoResize) + ThrowCapacityExceeded(newSize); + + Array.Resize(ref _data, Math.Max(newSize, _data.Length * 2)); } /// - /// Ensures the internal buffer can accommodate more s. + /// Throws an indicating that the buffer capacity was exceeded + /// while automatic resizing is disabled. /// - /// The number of additional s to fit. - /// - /// This checks against the current . If the capacity is insufficient, - /// the buffer grows to either the required size or doubles its current size. - /// + /// The total buffer size that was required. + /// Always thrown. + [MethodImpl(MethodImplOptions.NoInlining)] + private void ThrowCapacityExceeded(int requiredSize) + { + throw new InvalidOperationException( + $"Not enough capacity to write {requiredSize - _position} byte(s). " + + $"Position={_position}, Capacity={_data.Length}, RequiredSize={requiredSize}"); + } + + /// + /// Ensures that the internal buffer can accommodate more bytes + /// from the current write position. + /// + /// The number of additional bytes that must fit. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureFit(int additionalSize) { - if (_data.Length < _position + additionalSize) + if (additionalSize > 0) { - Array.Resize(ref _data, Math.Max(_position + additionalSize, _data.Length * 2)); + ResizeIfNeed(_position + additionalSize); } } @@ -275,8 +295,7 @@ public int SetPosition(int position) /// The value to write. public void Put(Guid value) { - if (_autoResize) - ResizeIfNeed(_position + GuidSize); + ResizeIfNeed(_position + GuidSize); value.TryWriteBytes(_data.AsSpan(_position)); _position += GuidSize; } @@ -307,8 +326,7 @@ public void Put(byte[] data) /// The span of data to write. public void Put(ReadOnlySpan data) { - if (_autoResize) - ResizeIfNeed(_position + data.Length); + ResizeIfNeed(_position + data.Length); data.CopyTo(_data.AsSpan(_position)); _position += data.Length; } @@ -321,8 +339,7 @@ public void Put(ReadOnlySpan data) /// The number of elements to write. public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) { - if (_autoResize) - ResizeIfNeed(_position + 2 + length); + ResizeIfNeed(_position + 2 + length); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -351,8 +368,7 @@ public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) /// The number of s to write. public void PutBytesWithLength(byte[] data, int offset, ushort length) { - if (_autoResize) - ResizeIfNeed(_position + 2 + length); + ResizeIfNeed(_position + 2 + length); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -389,8 +405,7 @@ public void PutArray(Array arr, int sz) { ushort length = arr == null ? (ushort)0 : (ushort)arr.Length; sz *= length; - if (_autoResize) - ResizeIfNeed(_position + sz + 2); + ResizeIfNeed(_position + sz + 2); FastBitConverter.GetBytes(_data, _position, length); if (arr != null) Buffer.BlockCopy(arr, 0, _data, _position + 2, sz); @@ -421,8 +436,7 @@ public unsafe void PutSpan(Span span) where T : unmanaged var length = (ushort)span.Length; var byteLength = length * sizeof(T); - if (_autoResize) - ResizeIfNeed(_position + byteLength + 2); + ResizeIfNeed(_position + byteLength + 2); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -533,8 +547,7 @@ public void Put(IPEndPoint endPoint) throw new ArgumentException($"Unsupported address family: {endPoint.AddressFamily}"); } - if (_autoResize) - ResizeIfNeed(_position + 1 + addressSize + 2); + ResizeIfNeed(_position + 1 + addressSize + 2); _data[_position++] = familyFlag; @@ -566,8 +579,7 @@ public void PutLargeString(string value) int size = uTF8Encoding.GetByteCount(value); Put(size); - if (_autoResize) - ResizeIfNeed(_position + size); + ResizeIfNeed(_position + size); uTF8Encoding.GetBytes(value, 0, value.Length, _data, _position); _position += size; @@ -595,8 +607,7 @@ public void Put(string value, int maxLength = 0) int length = maxLength > 0 && value.Length > maxLength ? maxLength : value.Length; int maxSize = uTF8Encoding.GetMaxByteCount(length); - if (_autoResize) - ResizeIfNeed(_position + maxSize + sizeof(ushort)); + ResizeIfNeed(_position + maxSize + sizeof(ushort)); int size = uTF8Encoding.GetBytes(value, 0, length, _data, _position + sizeof(ushort)); if (size == 0) { @@ -617,8 +628,7 @@ public void Put(string value, int maxLength = 0) public unsafe void PutUnmanaged(T value) where T : unmanaged { int size = sizeof(T); - if (_autoResize) - ResizeIfNeed(_position + size); + ResizeIfNeed(_position + size); FastBitConverter.GetBytes(_data, _position, value); _position += size; } @@ -654,10 +664,7 @@ public void PutNullableUnmanaged(T? value) where T : unmanaged public unsafe void PutEnum(T value) where T : unmanaged, Enum { var size = sizeof(T); - if (_autoResize) - { - ResizeIfNeed(_position + size); - } + ResizeIfNeed(_position + size); FastBitConverter.GetBytes(_data, _position, value); _position += size; From 584ae16122faf01021bed456310e2e495f700daa Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 22:32:15 +0300 Subject: [PATCH 179/200] revert --- LiteNetLib/Utils/NetDataWriter.cs | 91 ++++++++++++++----------------- 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 4a508b44..3c3892f1 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Net; using System.Net.Sockets; using System.Runtime.CompilerServices; @@ -125,56 +125,36 @@ public static NetDataWriter FromString(string value) } /// - /// Ensures that the internal buffer is at least bytes long. + /// Ensures the internal buffer is at least . /// /// The required minimum size of the buffer. - /// - /// Thrown when exceeds the current buffer capacity - /// and automatic resizing is disabled. - /// - /// - /// Thrown when is negative. - /// + /// + /// If an allocation is necessary, the buffer grows to either + /// or doubles its current size, whichever is larger. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ResizeIfNeed(int newSize) { - if (newSize < 0) - ThrowCapacityExceeded(newSize); - - if (_data.Length >= newSize) - return; - - if (!_autoResize) - ThrowCapacityExceeded(newSize); - - Array.Resize(ref _data, Math.Max(newSize, _data.Length * 2)); - } - - /// - /// Throws an indicating that the buffer capacity was exceeded - /// while automatic resizing is disabled. - /// - /// The total buffer size that was required. - /// Always thrown. - [MethodImpl(MethodImplOptions.NoInlining)] - private void ThrowCapacityExceeded(int requiredSize) - { - throw new InvalidOperationException( - $"Not enough capacity to write {requiredSize - _position} byte(s). " + - $"Position={_position}, Capacity={_data.Length}, RequiredSize={requiredSize}"); + if (_data.Length < newSize) + { + Array.Resize(ref _data, Math.Max(newSize, _data.Length * 2)); + } } /// - /// Ensures that the internal buffer can accommodate more bytes - /// from the current write position. + /// Ensures the internal buffer can accommodate more s. /// - /// The number of additional bytes that must fit. + /// The number of additional s to fit. + /// + /// This checks against the current . If the capacity is insufficient, + /// the buffer grows to either the required size or doubles its current size. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public void EnsureFit(int additionalSize) { - if (additionalSize > 0) + if (_data.Length < _position + additionalSize) { - ResizeIfNeed(_position + additionalSize); + Array.Resize(ref _data, Math.Max(_position + additionalSize, _data.Length * 2)); } } @@ -295,7 +275,8 @@ public int SetPosition(int position) /// The value to write. public void Put(Guid value) { - ResizeIfNeed(_position + GuidSize); + if (_autoResize) + ResizeIfNeed(_position + GuidSize); value.TryWriteBytes(_data.AsSpan(_position)); _position += GuidSize; } @@ -326,7 +307,8 @@ public void Put(byte[] data) /// The span of data to write. public void Put(ReadOnlySpan data) { - ResizeIfNeed(_position + data.Length); + if (_autoResize) + ResizeIfNeed(_position + data.Length); data.CopyTo(_data.AsSpan(_position)); _position += data.Length; } @@ -339,7 +321,8 @@ public void Put(ReadOnlySpan data) /// The number of elements to write. public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) { - ResizeIfNeed(_position + 2 + length); + if (_autoResize) + ResizeIfNeed(_position + 2 + length); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -368,7 +351,8 @@ public void PutSBytesWithLength(sbyte[] data, int offset, ushort length) /// The number of s to write. public void PutBytesWithLength(byte[] data, int offset, ushort length) { - ResizeIfNeed(_position + 2 + length); + if (_autoResize) + ResizeIfNeed(_position + 2 + length); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -405,7 +389,8 @@ public void PutArray(Array arr, int sz) { ushort length = arr == null ? (ushort)0 : (ushort)arr.Length; sz *= length; - ResizeIfNeed(_position + sz + 2); + if (_autoResize) + ResizeIfNeed(_position + sz + 2); FastBitConverter.GetBytes(_data, _position, length); if (arr != null) Buffer.BlockCopy(arr, 0, _data, _position + 2, sz); @@ -436,7 +421,8 @@ public unsafe void PutSpan(Span span) where T : unmanaged var length = (ushort)span.Length; var byteLength = length * sizeof(T); - ResizeIfNeed(_position + byteLength + 2); + if (_autoResize) + ResizeIfNeed(_position + byteLength + 2); FastBitConverter.GetBytes(_data, _position, length); _position += 2; @@ -547,7 +533,8 @@ public void Put(IPEndPoint endPoint) throw new ArgumentException($"Unsupported address family: {endPoint.AddressFamily}"); } - ResizeIfNeed(_position + 1 + addressSize + 2); + if (_autoResize) + ResizeIfNeed(_position + 1 + addressSize + 2); _data[_position++] = familyFlag; @@ -579,7 +566,8 @@ public void PutLargeString(string value) int size = uTF8Encoding.GetByteCount(value); Put(size); - ResizeIfNeed(_position + size); + if (_autoResize) + ResizeIfNeed(_position + size); uTF8Encoding.GetBytes(value, 0, value.Length, _data, _position); _position += size; @@ -607,7 +595,8 @@ public void Put(string value, int maxLength = 0) int length = maxLength > 0 && value.Length > maxLength ? maxLength : value.Length; int maxSize = uTF8Encoding.GetMaxByteCount(length); - ResizeIfNeed(_position + maxSize + sizeof(ushort)); + if (_autoResize) + ResizeIfNeed(_position + maxSize + sizeof(ushort)); int size = uTF8Encoding.GetBytes(value, 0, length, _data, _position + sizeof(ushort)); if (size == 0) { @@ -628,7 +617,8 @@ public void Put(string value, int maxLength = 0) public unsafe void PutUnmanaged(T value) where T : unmanaged { int size = sizeof(T); - ResizeIfNeed(_position + size); + if (_autoResize) + ResizeIfNeed(_position + size); FastBitConverter.GetBytes(_data, _position, value); _position += size; } @@ -664,7 +654,10 @@ public void PutNullableUnmanaged(T? value) where T : unmanaged public unsafe void PutEnum(T value) where T : unmanaged, Enum { var size = sizeof(T); - ResizeIfNeed(_position + size); + if (_autoResize) + { + ResizeIfNeed(_position + size); + } FastBitConverter.GetBytes(_data, _position, value); _position += size; From 9c7a93df030b855e9411e3f040116582de8f41ac Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 22:34:13 +0300 Subject: [PATCH 180/200] Length optimization --- LiteNetLib/Utils/NetDataWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 3c3892f1..901e3abf 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -97,7 +97,7 @@ public static NetDataWriter FromBytes(byte[] bytes, bool copy) /// Length of array public static NetDataWriter FromBytes(byte[] bytes, int offset, int length) { - var netDataWriter = new NetDataWriter(true, bytes.Length); + var netDataWriter = new NetDataWriter(true, length); netDataWriter.Put(bytes, offset, length); return netDataWriter; } From a05e8c7585c1c3f99f44a9006812c0128c601586 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 22:36:11 +0300 Subject: [PATCH 181/200] Fix doc --- LiteNetLib/Utils/NetDataWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 901e3abf..639f1fae 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -574,7 +574,7 @@ public void PutLargeString(string value) } /// - /// Serializes a string using a 2-byte length header. + /// Serializes a string using a 2-byte length header. /// /// The string to write to the buffer. /// From 91d510b88eddc7997e2a9a00beefbc973afac9d9 Mon Sep 17 00:00:00 2001 From: FUTURE-SL Date: Wed, 25 Mar 2026 22:47:49 +0300 Subject: [PATCH 182/200] Update NetDataWriter.cs --- LiteNetLib/Utils/NetDataWriter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 639f1fae..9d693ba5 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -243,7 +243,7 @@ public int SetPosition(int position) /// Serializes a value as a . ///
    /// The value to write. - public void Put(char value) => Put((ushort)value); + public void Put(char value) => PutUnmanaged(value); /// /// Serializes a value. From 4b3ed86aa47d4a12feb6e3c88b29a9b8621b856a Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:08:02 +0100 Subject: [PATCH 183/200] Update docs --- LiteNetLib/NatPunchModule.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/LiteNetLib/NatPunchModule.cs b/LiteNetLib/NatPunchModule.cs index 94251a86..3259384b 100644 --- a/LiteNetLib/NatPunchModule.cs +++ b/LiteNetLib/NatPunchModule.cs @@ -176,8 +176,10 @@ private void Send< /// /// Sends NAT introduction packets to both the host and the client to facilitate punchthrough. - /// This is typically called by a mediator (Master Server). /// + /// + /// This is typically called by a mediator (e.g. a master server). + /// /// Internal (LAN) endpoint of the host. /// External (WAN) endpoint of the host. /// Internal (LAN) endpoint of the client. From 6b1fcbf2cd72c84b805f58f00d66edc630bc9cd6 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:09:51 +0100 Subject: [PATCH 184/200] Update docs --- LiteNetLib/NetPacket.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LiteNetLib/NetPacket.cs b/LiteNetLib/NetPacket.cs index e22541ff..fcb271e9 100644 --- a/LiteNetLib/NetPacket.cs +++ b/LiteNetLib/NetPacket.cs @@ -202,9 +202,9 @@ public NetPacket(PacketProperty property, int payloadSize) public int HeaderSize => HeaderSizes[RawData[0] & 0x1F]; /// - /// Performs a basic sanity check on the packet header and size. + /// Performs a basic check on the packet header and size. /// - /// True if the packet property is valid and the size is sufficient for the headers. + /// if the packet property is valid and the size is sufficient for the headers. public bool Verify() { byte property = (byte)(RawData[0] & 0x1F); From bdaa143792b0d89c7273ca86b350e65ce858b023 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:29:08 +0100 Subject: [PATCH 185/200] Use spans for put string --- LiteNetLib/Utils/NetDataWriter.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/Utils/NetDataWriter.cs b/LiteNetLib/Utils/NetDataWriter.cs index 9d693ba5..24f09b8d 100644 --- a/LiteNetLib/Utils/NetDataWriter.cs +++ b/LiteNetLib/Utils/NetDataWriter.cs @@ -593,11 +593,16 @@ public void Put(string value, int maxLength = 0) return; } - int length = maxLength > 0 && value.Length > maxLength ? maxLength : value.Length; - int maxSize = uTF8Encoding.GetMaxByteCount(length); + ReadOnlySpan source = value.AsSpan(); + if (maxLength > 0 && source.Length > maxLength) + { + source = source.Slice(0, maxLength); + } + + int maxSize = uTF8Encoding.GetMaxByteCount(source.Length); if (_autoResize) ResizeIfNeed(_position + maxSize + sizeof(ushort)); - int size = uTF8Encoding.GetBytes(value, 0, length, _data, _position + sizeof(ushort)); + int size = uTF8Encoding.GetBytes(source, _data.AsSpan(_position + sizeof(ushort))); if (size == 0) { Put((ushort)0); From dfbd90bd35df83492439088b5d2cc6082c6427e9 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:50:34 +0100 Subject: [PATCH 186/200] Update docs --- LiteNetLib/BaseChannel.cs | 2 +- LiteNetLib/NetConstants.cs | 7 ++++++- LiteNetLib/NetPacket.cs | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/BaseChannel.cs b/LiteNetLib/BaseChannel.cs index f8b6fd9c..1dd969c5 100644 --- a/LiteNetLib/BaseChannel.cs +++ b/LiteNetLib/BaseChannel.cs @@ -4,7 +4,7 @@ namespace LiteNetLib { /// - /// Base class for all communication channels (Reliable, Unreliable, Sequenced).
    + /// Base class for reliable and sequenced communication channels.
    /// Handles the queuing and scheduling of outgoing packets. ///
    internal abstract class BaseChannel diff --git a/LiteNetLib/NetConstants.cs b/LiteNetLib/NetConstants.cs index 75dbea85..947cc865 100644 --- a/LiteNetLib/NetConstants.cs +++ b/LiteNetLib/NetConstants.cs @@ -112,8 +112,13 @@ public static class NetConstants public static readonly int MaxUnreliableDataSize = MaxPacketSize - HeaderSize; /// - /// Maximum number of simultaneous connection attempts (pending connections) allowed per peer. + /// Maximum possible value for . /// + /// + /// This value is used to distinguish between different connection instances from the same .
    + /// It allows the receiver to identify and discard packets belonging to previous connection attempts that may arrive + /// late due to network jitter, even if they originate from the same address and port.
    + ///
    public const byte MaxConnectionNumber = 4; } } diff --git a/LiteNetLib/NetPacket.cs b/LiteNetLib/NetPacket.cs index fcb271e9..d0ecdd6a 100644 --- a/LiteNetLib/NetPacket.cs +++ b/LiteNetLib/NetPacket.cs @@ -77,9 +77,12 @@ public PacketProperty Property } /// - /// Gets or sets the connection number used to distinguish between multiple connections from the same endpoint.
    + /// Gets or sets the connection number used to distinguish between multiple connection instances from the same endpoint. /// Stored in bits 6 and 7 of the first byte (0x60 mask). ///
    + /// + /// Used to discard packets from previous connections made in the same frame/time. + /// public byte ConnectionNumber { get => (byte)((RawData[0] & 0x60) >> 5); From 79e9af312e2a8e75d158bbd177358423b4df76f5 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Wed, 25 Mar 2026 22:55:34 +0200 Subject: [PATCH 187/200] generate docs --- docs/api/LiteNetLib.ConnectionRequest.html | 19 ++++-- .../LiteNetLib.EventBasedLiteNetListener.html | 54 +++++++++++------ ...LiteNetLib.EventBasedNatPunchListener.html | 11 ++-- .../api/LiteNetLib.EventBasedNetListener.html | 60 ++++++++++++------- docs/api/LiteNetLib.INatPunchListener.html | 29 +++++---- .../api/LiteNetLib.LiteConnectionRequest.html | 19 ++++-- docs/api/LiteNetLib.LiteNetManager.html | 10 +++- docs/api/LiteNetLib.NatAddressType.html | 11 ++-- docs/api/LiteNetLib.NatPunchModule.html | 57 ++++++++++++------ docs/api/LiteNetLib.NetConstants.html | 49 +++++++++++---- docs/api/LiteNetLib.NetEvent.EType.html | 35 +++++++---- docs/api/LiteNetLib.NetEvent.html | 42 ++++++++----- docs/api/LiteNetLib.NetStatistics.html | 58 +++++++++++------- docs/api/LiteNetLib.NetUtils.html | 53 ++++++++++++---- .../LiteNetLib.Utils.FastBitConverter.html | 31 ++++++++-- .../LiteNetLib.Utils.INetSerializable.html | 20 +++++-- docs/api/LiteNetLib.Utils.NetDataWriter.html | 2 +- .../LiteNetLib.Utils.NetPacketProcessor.html | 54 ++++++++++++----- docs/api/LiteNetLib.Utils.html | 3 +- docs/api/LiteNetLib.html | 15 +++-- docs/manifest.json | 14 ++--- 21 files changed, 450 insertions(+), 196 deletions(-) diff --git a/docs/api/LiteNetLib.ConnectionRequest.html b/docs/api/LiteNetLib.ConnectionRequest.html index 9b89b5ca..1c60018b 100644 --- a/docs/api/LiteNetLib.ConnectionRequest.html +++ b/docs/api/LiteNetLib.ConnectionRequest.html @@ -127,7 +127,8 @@

    Methods

    Accept()

    -
    +

    Accept connection and get new NetPeer as result

    +
    Declaration
    @@ -144,7 +145,8 @@
    Returns
    NetPeer - +

    Connected NetPeer

    + @@ -152,7 +154,8 @@
    Returns

    AcceptIfKey(string)

    -
    +

    Accepts the connection if the first string in the Data matches the provided key.

    +
    Declaration
    @@ -171,7 +174,8 @@
    Parameters
    string key - +

    The required string key to match.

    + @@ -186,10 +190,15 @@
    Returns
    NetPeer - +

    A new LiteNetPeer if the key matches and connection is accepted; otherwise, null.

    + +
    Remarks
    +

    This is a helper method for simple password/key validation. +If the key does not match or data is invalid, the connection is automatically rejected.

    +
    diff --git a/docs/api/LiteNetLib.EventBasedLiteNetListener.html b/docs/api/LiteNetLib.EventBasedLiteNetListener.html index 2c275bf9..9dcfbc72 100644 --- a/docs/api/LiteNetLib.EventBasedLiteNetListener.html +++ b/docs/api/LiteNetLib.EventBasedLiteNetListener.html @@ -95,7 +95,8 @@

    Methods

    ClearConnectionRequestEvent()

    -
    +

    Clears all subscribers from ConnectionRequestEvent.

    +
    Declaration
    @@ -105,7 +106,8 @@
    Declaration

    ClearDeliveryEvent()

    -
    +

    Clears all subscribers from DeliveryEvent.

    +
    Declaration
    @@ -115,7 +117,8 @@
    Declaration

    ClearNetworkErrorEvent()

    -
    +

    Clears all subscribers from NetworkErrorEvent.

    +
    Declaration
    @@ -125,7 +128,8 @@
    Declaration

    ClearNetworkLatencyUpdateEvent()

    -
    +

    Clears all subscribers from NetworkLatencyUpdateEvent.

    +
    Declaration
    @@ -135,7 +139,8 @@
    Declaration

    ClearNetworkReceiveEvent()

    -
    +

    Clears all subscribers from NetworkReceiveEvent.

    +
    Declaration
    @@ -145,7 +150,8 @@
    Declaration

    ClearNetworkReceiveUnconnectedEvent()

    -
    +

    Clears all subscribers from NetworkReceiveUnconnectedEvent.

    +
    Declaration
    @@ -155,7 +161,8 @@
    Declaration

    ClearPeerAddressChangedEvent()

    -
    +

    Clears all subscribers from PeerAddressChangedEvent.

    +
    Declaration
    @@ -165,7 +172,8 @@
    Declaration

    ClearPeerConnectedEvent()

    -
    +

    Clears all subscribers from PeerConnectedEvent.

    +
    Declaration
    @@ -175,7 +183,8 @@
    Declaration

    ClearPeerDisconnectedEvent()

    -
    +

    Clears all subscribers from PeerDisconnectedEvent.

    +
    Declaration
    @@ -186,7 +195,8 @@

    Events

    ConnectionRequestEvent

    -
    +

    Occurs when a new connection request is received.

    +
    Declaration
    @@ -210,7 +220,8 @@
    Event Type

    DeliveryEvent

    -
    +

    Occurs when a reliable packet is successfully delivered or acknowledged.

    +
    Declaration
    @@ -234,7 +245,8 @@
    Event Type

    NetworkErrorEvent

    -
    +

    Occurs when a network error is detected in the underlying socket.

    +
    Declaration
    @@ -258,7 +270,8 @@
    Event Type

    NetworkLatencyUpdateEvent

    -
    +

    Occurs when the round-trip time (RTT) to a peer is updated.

    +
    Declaration
    @@ -282,7 +295,8 @@
    Event Type

    NetworkReceiveEvent

    -
    +

    Occurs when data is received from a connected peer.

    +
    Declaration
    @@ -306,7 +320,8 @@
    Event Type

    NetworkReceiveUnconnectedEvent

    -
    +

    Occurs when a message is received from an unconnected endpoint.

    +
    Declaration
    @@ -330,7 +345,8 @@
    Event Type

    PeerAddressChangedEvent

    -
    +

    Occurs when a peer's remote address changes.

    +
    Declaration
    @@ -354,7 +370,8 @@
    Event Type

    PeerConnectedEvent

    -
    +

    Occurs when a new peer has successfully connected.

    +
    Declaration
    @@ -378,7 +395,8 @@
    Event Type

    PeerDisconnectedEvent

    -
    +

    Occurs when a peer disconnects or the connection is lost.

    +
    Declaration
    diff --git a/docs/api/LiteNetLib.EventBasedNatPunchListener.html b/docs/api/LiteNetLib.EventBasedNatPunchListener.html index 0d78135f..64a64655 100644 --- a/docs/api/LiteNetLib.EventBasedNatPunchListener.html +++ b/docs/api/LiteNetLib.EventBasedNatPunchListener.html @@ -9,7 +9,7 @@ - + @@ -71,7 +71,8 @@

    Class EventBasedNatPunchListener

    -
    +

    An implementation of INatPunchListener that maps callbacks to events.

    +
    Inheritance
    @@ -93,7 +94,8 @@

    Events

    NatIntroductionRequest

    -
    +

    Event triggered when a NAT introduction request is received.

    +
    Declaration
    @@ -117,7 +119,8 @@
    Event Type

    NatIntroductionSuccess

    -
    +

    Event triggered when NAT punchthrough is successfully completed.

    +
    Declaration
    diff --git a/docs/api/LiteNetLib.EventBasedNetListener.html b/docs/api/LiteNetLib.EventBasedNetListener.html index 0f67c1fa..d319a771 100644 --- a/docs/api/LiteNetLib.EventBasedNetListener.html +++ b/docs/api/LiteNetLib.EventBasedNetListener.html @@ -95,7 +95,8 @@

    Methods

    ClearConnectionRequestEvent()

    -
    +

    Clears all subscribers from ConnectionRequestEvent.

    +
    Declaration
    @@ -105,7 +106,8 @@
    Declaration

    ClearDeliveryEvent()

    -
    +

    Clears all subscribers from DeliveryEvent.

    +
    Declaration
    @@ -115,7 +117,8 @@
    Declaration

    ClearNetworkErrorEvent()

    -
    +

    Clears all subscribers from NetworkErrorEvent.

    +
    Declaration
    @@ -125,7 +128,8 @@
    Declaration

    ClearNetworkLatencyUpdateEvent()

    -
    +

    Clears all subscribers from NetworkLatencyUpdateEvent.

    +
    Declaration
    @@ -135,7 +139,8 @@
    Declaration

    ClearNetworkReceiveEvent()

    -
    +

    Clears all subscribers from NetworkReceiveEvent.

    +
    Declaration
    @@ -145,7 +150,8 @@
    Declaration

    ClearNetworkReceiveUnconnectedEvent()

    -
    +

    Clears all subscribers from NetworkReceiveUnconnectedEvent.

    +
    Declaration
    @@ -155,7 +161,8 @@
    Declaration

    ClearNtpResponseEvent()

    -
    +

    Clears all subscribers from NtpResponseEvent.

    +
    Declaration
    @@ -165,7 +172,8 @@
    Declaration

    ClearPeerAddressChangedEvent()

    -
    +

    Clears all subscribers from PeerAddressChangedEvent.

    +
    Declaration
    @@ -175,7 +183,8 @@
    Declaration

    ClearPeerConnectedEvent()

    -
    +

    Clears all subscribers from PeerConnectedEvent.

    +
    Declaration
    @@ -185,7 +194,8 @@
    Declaration

    ClearPeerDisconnectedEvent()

    -
    +

    Clears all subscribers from PeerDisconnectedEvent.

    +
    Declaration
    @@ -196,7 +206,8 @@

    Events

    ConnectionRequestEvent

    -
    +

    Occurs when a new connection request is received.

    +
    Declaration
    @@ -220,7 +231,8 @@
    Event Type

    DeliveryEvent

    -
    +

    Occurs when a reliable packet is successfully delivered or acknowledged.

    +
    Declaration
    @@ -244,7 +256,8 @@
    Event Type

    NetworkErrorEvent

    -
    +

    Occurs when a network error is detected in the underlying socket.

    +
    Declaration
    @@ -268,7 +281,8 @@
    Event Type

    NetworkLatencyUpdateEvent

    -
    +

    Occurs when the round-trip time (RTT) to a peer is updated.

    +
    Declaration
    @@ -292,7 +306,8 @@
    Event Type

    NetworkReceiveEvent

    -
    +

    Occurs when data is received from a connected peer.

    +
    Declaration
    @@ -316,7 +331,8 @@
    Event Type

    NetworkReceiveUnconnectedEvent

    -
    +

    Occurs when a message is received from an unconnected endpoint.

    +
    Declaration
    @@ -340,7 +356,8 @@
    Event Type

    NtpResponseEvent

    -
    +

    Occurs when an NTP response is received.

    +
    Declaration
    @@ -364,7 +381,8 @@
    Event Type

    PeerAddressChangedEvent

    -
    +

    Occurs when a peer's remote address changes.

    +
    Declaration
    @@ -388,7 +406,8 @@
    Event Type

    PeerConnectedEvent

    -
    +

    Occurs when a new peer has successfully connected.

    +
    Declaration
    @@ -412,7 +431,8 @@
    Event Type

    PeerDisconnectedEvent

    -
    +

    Occurs when a peer disconnects or the connection is lost.

    +
    Declaration
    diff --git a/docs/api/LiteNetLib.INatPunchListener.html b/docs/api/LiteNetLib.INatPunchListener.html index 6f93cc69..579fcb36 100644 --- a/docs/api/LiteNetLib.INatPunchListener.html +++ b/docs/api/LiteNetLib.INatPunchListener.html @@ -9,7 +9,7 @@ - + @@ -71,7 +71,8 @@

    Interface INatPunchListener

    -
    +

    Interface for handling events related to NAT punchthrough and introduction.

    +
    Namespace: LiteNetLib
    Assembly: LiteNetLib.dll
    @@ -85,7 +86,8 @@

    Methods

    OnNatIntroductionRequest(IPEndPoint, IPEndPoint, string)

    -
    +

    Called when a NAT introduction request is received from the mediator server.

    +
    Declaration
    @@ -104,17 +106,20 @@
    Parameters
    IPEndPoint localEndPoint - +

    The local endpoint of the client requesting connection.

    + IPEndPoint remoteEndPoint - +

    The remote endpoint of the client requesting connection.

    + string token - +

    Custom data token associated with the request.

    + @@ -122,7 +127,8 @@
    Parameters

    OnNatIntroductionSuccess(IPEndPoint, NatAddressType, string)

    -
    +

    Called when NAT punchthrough is successful and a direct connection can be established.

    +
    Declaration
    @@ -141,17 +147,20 @@
    Parameters
    IPEndPoint targetEndPoint - +

    The resolved endpoint of the remote peer.

    + NatAddressType type - +

    The type of address (Internal or External) that succeeded.

    + string token - +

    Custom data token associated with the request.

    + diff --git a/docs/api/LiteNetLib.LiteConnectionRequest.html b/docs/api/LiteNetLib.LiteConnectionRequest.html index b624712a..68fb5ad5 100644 --- a/docs/api/LiteNetLib.LiteConnectionRequest.html +++ b/docs/api/LiteNetLib.LiteConnectionRequest.html @@ -90,7 +90,8 @@

    Fields

    RemoteEndPoint

    -
    +

    The remote endpoint (IP and Port) of the peer requesting the connection.

    +
    Declaration
    @@ -117,7 +118,8 @@

    Properties

    Data

    -
    +

    Data sent by the remote peer in the connection request.

    +
    Declaration
    @@ -171,7 +173,8 @@
    Returns

    AcceptIfKey(string)

    -
    +

    Accepts the connection if the first string in the Data matches the provided key.

    +
    Declaration
    @@ -190,7 +193,8 @@
    Parameters
    string key - +

    The required string key to match.

    + @@ -205,10 +209,15 @@
    Returns
    LiteNetPeer - +

    A new LiteNetPeer if the key matches and connection is accepted; otherwise, null.

    + +
    Remarks
    +

    This is a helper method for simple password/key validation. +If the key does not match or data is invalid, the connection is automatically rejected.

    +
    diff --git a/docs/api/LiteNetLib.LiteNetManager.html b/docs/api/LiteNetLib.LiteNetManager.html index be29695b..b687ab16 100644 --- a/docs/api/LiteNetLib.LiteNetManager.html +++ b/docs/api/LiteNetLib.LiteNetManager.html @@ -1015,7 +1015,8 @@
    Property Value

    ExtraPacketSizeForLayer

    -
    +

    Gets the additional size in bytes required by the active PacketLayerBase.

    +
    Declaration
    @@ -1036,6 +1037,11 @@
    Property Value
    +
    Remarks
    +

    This value is used by NetManager to calculate the available MTU for user data.
    +If a packet layer is active (e.g., for encryption or CRC), this returns the overhead added to every packet. +Returns 0 if no packet layer is assigned.

    +
    @@ -3631,7 +3637,7 @@
    Returns
    bool -

    True if peer with id exist, otherwise false

    +

    true if peer with id exist; otherwise false

    diff --git a/docs/api/LiteNetLib.NatAddressType.html b/docs/api/LiteNetLib.NatAddressType.html index 3dcf0b2d..feae78d5 100644 --- a/docs/api/LiteNetLib.NatAddressType.html +++ b/docs/api/LiteNetLib.NatAddressType.html @@ -9,7 +9,7 @@ - + @@ -72,7 +72,8 @@

    Enum NatAddressType

    -
    +

    Specifies the type of network address discovered during NAT punchthrough.

    +
    Namespace: LiteNetLib
    Assembly: LiteNetLib.dll
    @@ -92,11 +93,13 @@

    Fields External - +

    Publicly accessible address on the wide area network (WAN).

    + Internal - +

    Address within the local area network (LAN).

    + diff --git a/docs/api/LiteNetLib.NatPunchModule.html b/docs/api/LiteNetLib.NatPunchModule.html index 27210701..a789e407 100644 --- a/docs/api/LiteNetLib.NatPunchModule.html +++ b/docs/api/LiteNetLib.NatPunchModule.html @@ -90,7 +90,8 @@

    Fields

    MaxTokenLength

    -
    +

    Maximum allowed length for the NAT introduction token string.

    +
    Declaration
    @@ -142,7 +143,8 @@

    Methods

    Init(INatPunchListener)

    -
    +

    Initializes the NAT punch module with a listener to handle punchthrough events.

    +
    Declaration
    @@ -161,7 +163,8 @@
    Parameters
    INatPunchListener listener - +

    The listener implementation that will receive NAT events.

    + @@ -169,7 +172,8 @@
    Parameters

    NatIntroduce(IPEndPoint, IPEndPoint, IPEndPoint, IPEndPoint, string)

    -
    +

    Sends NAT introduction packets to both the host and the client to facilitate punchthrough.

    +
    Declaration
    @@ -188,45 +192,58 @@
    Parameters
    IPEndPoint hostInternal - +

    Internal (LAN) endpoint of the host.

    + IPEndPoint hostExternal - +

    External (WAN) endpoint of the host.

    + IPEndPoint clientInternal - +

    Internal (LAN) endpoint of the client.

    + IPEndPoint clientExternal - +

    External (WAN) endpoint of the client.

    + string additionalInfo - +

    Custom token or data to include in the introduction.

    + +
    Remarks
    +

    This is typically called by a mediator (e.g. a master server).

    +

    PollEvents()

    -
    +

    Triggers queued NAT punchthrough events (Success or Request) on the provided INatPunchListener.

    +
    Declaration
    public void PollEvents()
    +
    Remarks
    +

    This should be called from the main thread if UnsyncedEvents is false.

    +

    SendNatIntroduceRequest(IPEndPoint, string)

    -
    +

    Sends a request to the Master Server to introduce this peer to another peer.

    +
    Declaration
    @@ -245,12 +262,14 @@
    Parameters
    IPEndPoint masterServerEndPoint - +

    The endpoint of the Master Server.

    + string additionalInfo - +

    Custom token to identify the connection or room.

    + @@ -258,7 +277,8 @@
    Parameters

    SendNatIntroduceRequest(string, int, string)

    -
    +

    Sends a request to the Master Server to introduce this peer to another peer.

    +
    Declaration
    @@ -277,17 +297,20 @@
    Parameters
    string host - +

    The hostname or IP of the Master Server.

    + int port - +

    The port of the Master Server.

    + string additionalInfo - +

    Custom token to identify the connection or room.

    + diff --git a/docs/api/LiteNetLib.NetConstants.html b/docs/api/LiteNetLib.NetConstants.html index 1b95fedf..e89a2a94 100644 --- a/docs/api/LiteNetLib.NetConstants.html +++ b/docs/api/LiteNetLib.NetConstants.html @@ -90,7 +90,9 @@

    Fields

    ChanneledHeaderSize

    -
    +

    Size of the header for sequenced or reliable messages in bytes.
    +Includes HeaderSize, Sequence, and ChannelId.

    +
    Declaration
    @@ -114,7 +116,8 @@
    Field Value

    DefaultWindowSize

    -
    +

    Default window size for reliable channels (number of packets).

    +
    Declaration
    @@ -138,7 +141,9 @@
    Field Value

    FragmentHeaderSize

    -
    +

    Additional header size required for fragmented packets in bytes.
    +Includes FragmentId, FragmentPart, and FragmentsTotal.

    +
    Declaration
    @@ -162,7 +167,9 @@
    Field Value

    FragmentedHeaderTotalSize

    -
    +

    Total header size for a fragmented channeled packet in bytes.
    +Combines ChanneledHeaderSize and FragmentHeaderSize.

    +
    Declaration
    @@ -186,7 +193,8 @@
    Field Value

    HalfMaxSequence

    -
    +

    Half of the MaxSequence, used for sequence comparison and wrap-around logic.

    +
    Declaration
    @@ -210,7 +218,8 @@
    Field Value

    HeaderSize

    -
    +

    Size of the base packet header (PacketProperty) in bytes.

    +
    Declaration
    @@ -234,7 +243,8 @@
    Field Value

    InitialMtu

    -
    +

    The starting Maximum Transmission Unit (MTU) used for new connections before path MTU discovery.

    +
    Declaration
    @@ -258,7 +268,8 @@
    Field Value

    MaxConnectionNumber

    -
    +

    Maximum possible value for LiteNetLib.NetPacket.ConnectionNumber.

    +
    Declaration
    @@ -279,10 +290,16 @@
    Field Value
    +
    Remarks
    +

    This value is used to distinguish between different connection instances from the same IPEndPoint.
    +It allows the receiver to identify and discard packets belonging to previous connection attempts that may arrive +late due to network jitter, even if they originate from the same address and port.

    +

    MaxPacketSize

    -
    +

    Maximum possible packet size allowed by the library based on the largest supported MTU.

    +
    Declaration
    @@ -306,7 +323,8 @@
    Field Value

    MaxSequence

    -
    +

    Maximum possible sequence number before wrapping back to zero.

    +
    Declaration
    @@ -330,7 +348,9 @@
    Field Value

    MaxUnreliableDataSize

    -
    +

    Maximum payload size for a single unreliable packet in bytes.
    +Calculated as MaxPacketSize - HeaderSize.

    +
    Declaration
    @@ -354,7 +374,9 @@
    Field Value

    SocketBufferSize

    -
    +

    Size of the underlying UDP socket receive and send buffers in bytes.
    +Default is 1MB.

    +
    Declaration
    @@ -378,7 +400,8 @@
    Field Value

    SocketTTL

    -
    +

    Time To Live (TTL) for the UDP packets.

    +
    Declaration
    diff --git a/docs/api/LiteNetLib.NetEvent.EType.html b/docs/api/LiteNetLib.NetEvent.EType.html index 86acddf9..40a3bc78 100644 --- a/docs/api/LiteNetLib.NetEvent.EType.html +++ b/docs/api/LiteNetLib.NetEvent.EType.html @@ -9,7 +9,7 @@ - + @@ -72,7 +72,8 @@

    Enum NetEvent.EType

    -
    +

    Specifies the category of the network event.

    +
    Namespace: LiteNetLib
    Assembly: LiteNetLib.dll
    @@ -92,43 +93,53 @@

    Fields Broadcast - +

    Broadcast message received.

    + Connect - +

    New peer connected.

    + ConnectionLatencyUpdated - +

    Round-trip time (RTT) for a peer has been updated.

    + ConnectionRequest - +

    Incoming connection request from a new peer.

    + Disconnect - +

    Peer disconnected.

    + Error - +

    Socket or internal protocol error occurred.

    + MessageDelivered - +

    Reliable message was successfully delivered to the remote peer.

    + PeerAddressChanged - +

    The IP address or port of an existing peer has changed (e.g., roaming).

    + Receive - +

    Data received from a connected peer.

    + ReceiveUnconnected - +

    Unconnected message received.

    + diff --git a/docs/api/LiteNetLib.NetEvent.html b/docs/api/LiteNetLib.NetEvent.html index bea06f3b..2235de1f 100644 --- a/docs/api/LiteNetLib.NetEvent.html +++ b/docs/api/LiteNetLib.NetEvent.html @@ -91,7 +91,8 @@

    Constructors

    NetEvent(LiteNetManager)

    -
    +

    Initializes a new instance of the NetEvent class.

    +
    Declaration
    @@ -110,7 +111,8 @@
    Parameters
    LiteNetManager manager - +

    The LiteNetManager that owns the packet pool and buffers for this event.

    + @@ -119,7 +121,8 @@

    Fields

    ChannelNumber

    -
    +

    The channel on which the packet was received.

    +
    Declaration
    @@ -143,7 +146,8 @@
    Field Value

    ConnectionRequest

    -
    +

    Information about an incoming connection. Only valid when Type is ConnectionRequest.

    +
    Declaration
    @@ -167,7 +171,8 @@
    Field Value

    DataReader

    -
    +

    A reader for accessing the payload of received data, broadcast, or unconnected messages.

    +
    Declaration
    @@ -191,7 +196,8 @@
    Field Value

    DeliveryMethod

    -
    +

    The delivery method used for the received packet. Only valid when Type is Receive.

    +
    Declaration
    @@ -215,7 +221,8 @@
    Field Value

    DisconnectReason

    -
    +

    The reason for a peer's disconnection. Only valid when Type is Disconnect.

    +
    Declaration
    @@ -239,7 +246,8 @@
    Field Value

    ErrorCode

    -
    +

    The specific socket error. Only valid when Type is Error.

    +
    Declaration
    @@ -263,7 +271,8 @@
    Field Value

    Latency

    -
    +

    The updated latency value in milliseconds. Only valid when Type is ConnectionLatencyUpdated.

    +
    Declaration
    @@ -287,7 +296,8 @@
    Field Value

    Next

    -
    +

    Reference to the next event in the pool or event queue.

    +
    Declaration
    @@ -311,7 +321,8 @@
    Field Value

    Peer

    -
    +

    The peer associated with this event. null for unconnected events.

    +
    Declaration
    @@ -335,7 +346,8 @@
    Field Value

    RemoteEndPoint

    -
    +

    The remote endpoint (IP and Port) from which the event originated.

    +
    Declaration
    @@ -359,7 +371,8 @@
    Field Value

    Type

    -
    +

    The type of network event that occurred.

    +
    Declaration
    @@ -383,7 +396,8 @@
    Field Value

    UserData

    -
    +

    Optional user data associated with a connection request or disconnect.

    +
    Declaration
    diff --git a/docs/api/LiteNetLib.NetStatistics.html b/docs/api/LiteNetLib.NetStatistics.html index 796ea08e..19c6e66b 100644 --- a/docs/api/LiteNetLib.NetStatistics.html +++ b/docs/api/LiteNetLib.NetStatistics.html @@ -9,7 +9,7 @@ - + @@ -71,7 +71,8 @@

    Class NetStatistics

    -
    +

    Thread-safe counter for network statistics including sent/received packets, bytes, and packet loss.

    +
    Inheritance
    @@ -90,7 +91,8 @@

    Properties

    BytesReceived

    -
    +

    Total number of bytes received.

    +
    Declaration
    @@ -115,7 +117,8 @@
    Property Value

    BytesSent

    -
    +

    Total number of bytes sent.

    +
    Declaration
    @@ -140,7 +143,8 @@
    Property Value

    PacketLoss

    -
    +

    Total number of packets lost during transmission.

    +
    Declaration
    @@ -165,7 +169,9 @@
    Property Value

    PacketLossPercent

    -
    +

    Percentage of sent packets that were lost. +Calculated as (PacketLoss * 100) / PacketsSent.

    +
    Declaration
    @@ -190,7 +196,8 @@
    Property Value

    PacketsReceived

    -
    +

    Total number of packets received.

    +
    Declaration
    @@ -215,7 +222,8 @@
    Property Value

    PacketsSent

    -
    +

    Total number of packets sent.

    +
    Declaration
    @@ -242,7 +250,8 @@

    Methods

    AddBytesReceived(long)

    -
    +

    Adds a specific amount to the total bytes received.

    +
    Declaration
    @@ -261,7 +270,8 @@
    Parameters
    long bytesReceived - +

    Number of bytes to add.

    + @@ -269,7 +279,8 @@
    Parameters

    AddBytesSent(long)

    -
    +

    Adds a specific amount to the total bytes sent.

    +
    Declaration
    @@ -288,7 +299,8 @@
    Parameters
    long bytesSent - +

    Number of bytes to add.

    + @@ -296,7 +308,8 @@
    Parameters

    AddPacketLoss(long)

    -
    +

    Adds a specific amount to the total packet loss count.

    +
    Declaration
    @@ -315,7 +328,8 @@
    Parameters
    long packetLoss - +

    Number of lost packets to add.

    + @@ -323,7 +337,8 @@
    Parameters

    IncrementPacketLoss()

    -
    +

    Increments the count of lost packets by one.

    +
    Declaration
    @@ -333,7 +348,8 @@
    Declaration

    IncrementPacketsReceived()

    -
    +

    Increments the count of received packets by one.

    +
    Declaration
    @@ -343,7 +359,8 @@
    Declaration

    IncrementPacketsSent()

    -
    +

    Increments the count of sent packets by one.

    +
    Declaration
    @@ -353,7 +370,8 @@
    Declaration

    Reset()

    -
    +

    Resets all statistical counters to zero.

    +
    Declaration
    @@ -363,7 +381,7 @@
    Declaration

    ToString()

    -

    Returns a string that represents the current object.

    +

    Returns a string representation of the current network statistics.

    Declaration
    @@ -381,7 +399,7 @@
    Returns
    string -

    A string that represents the current object.

    +

    A formatted string containing bytes received/sent, packets received/sent, and loss information.

    diff --git a/docs/api/LiteNetLib.NetUtils.html b/docs/api/LiteNetLib.NetUtils.html index bdd956e7..18dba861 100644 --- a/docs/api/LiteNetLib.NetUtils.html +++ b/docs/api/LiteNetLib.NetUtils.html @@ -216,7 +216,8 @@
    Parameters

    MakeEndPoint(string, int)

    -
    +

    Creates an IPEndPoint from a host string and a port.

    +
    Declaration
    @@ -235,12 +236,14 @@
    Parameters
    string hostStr - +

    The host name or IP address string to resolve.

    + int port - +

    The port number for the endpoint.

    + @@ -255,7 +258,8 @@
    Returns
    IPEndPoint - +

    A new IPEndPoint instance.

    + @@ -263,7 +267,8 @@
    Returns

    ResolveAddress(string)

    -
    +

    Resolves a host string into an IPAddress.

    +
    Declaration
    @@ -282,7 +287,8 @@
    Parameters
    string hostStr - +

    The host name or IP address string (e.g., "127.0.0.1", "localhost", or "google.com").

    + @@ -297,7 +303,28 @@
    Returns
    IPAddress - +

    The resolved IPAddress.

    + + + + +
    Remarks
    +

    This method handles "localhost" specifically, attempts to parse the string as a direct IP, +and falls back to DNS resolution. It prioritizes IPv6 if IPv6Support is enabled.

    +
    +
    Exceptions
    + + + + + + + + + + +
    TypeCondition
    ArgumentException

    Thrown when the address cannot be resolved or is invalid.

    +
    @@ -305,7 +332,8 @@
    Returns

    ResolveAddress(string, AddressFamily)

    -
    +

    Resolves a host string using DNS for a specific AddressFamily.

    +
    Declaration
    @@ -324,12 +352,14 @@
    Parameters
    string hostStr - +

    The host name to resolve via DNS.

    + AddressFamily addressFamily - +

    The preferred address family (e.g., InterNetwork or InterNetworkV6).

    + @@ -344,7 +374,8 @@
    Returns
    IPAddress - +

    The first IPAddress matching the family, or null if no match is found.

    + diff --git a/docs/api/LiteNetLib.Utils.FastBitConverter.html b/docs/api/LiteNetLib.Utils.FastBitConverter.html index 63a61722..ba3f4c92 100644 --- a/docs/api/LiteNetLib.Utils.FastBitConverter.html +++ b/docs/api/LiteNetLib.Utils.FastBitConverter.html @@ -90,7 +90,8 @@

    Methods

    GetBytes<T>(byte[], int, T)

    -
    +

    Converts a value of type T into a byte array starting at the specified index.

    +
    Declaration
    @@ -109,17 +110,20 @@
    Parameters
    byte[] bytes - +

    The destination byte array.

    + int startIndex - +

    The zero-based index in bytes at which to begin writing.

    + T value - +

    The value to be converted and written.

    + @@ -134,7 +138,24 @@
    Type Parameters
    T - +

    The type of the value to convert. Must be an unmanaged/blittable type.

    + + + + +
    Exceptions
    + + + + + + + + + + +
    TypeCondition
    IndexOutOfRangeException

    Thrown when the bytes array is too small to contain the value at the given startIndex.

    +
    diff --git a/docs/api/LiteNetLib.Utils.INetSerializable.html b/docs/api/LiteNetLib.Utils.INetSerializable.html index 5dbba128..f536537a 100644 --- a/docs/api/LiteNetLib.Utils.INetSerializable.html +++ b/docs/api/LiteNetLib.Utils.INetSerializable.html @@ -9,7 +9,7 @@ - + @@ -71,7 +71,8 @@

    Interface INetSerializable

    -
    +

    Interface for implementing custom data serialization for network transmission.

    +
    Namespace: LiteNetLib.Utils
    Assembly: LiteNetLib.dll
    @@ -79,13 +80,17 @@
    Syntax
    public interface INetSerializable
    +
    Remarks
    +

    This is the most efficient way to send complex objects as it avoids reflection.

    +

    Methods

    Deserialize(NetDataReader)

    -
    +

    Reads the object data from the provided NetDataReader.

    +
    Declaration
    @@ -104,7 +109,8 @@
    Parameters
    NetDataReader reader - +

    The reader to extract data from.

    + @@ -112,7 +118,8 @@
    Parameters

    Serialize(NetDataWriter)

    -
    +

    Writes the object data into the provided NetDataWriter.

    +
    Declaration
    @@ -131,7 +138,8 @@
    Parameters
    NetDataWriter writer - +

    The writer to pack data into.

    + diff --git a/docs/api/LiteNetLib.Utils.NetDataWriter.html b/docs/api/LiteNetLib.Utils.NetDataWriter.html index d24d1d4a..39a22e04 100644 --- a/docs/api/LiteNetLib.Utils.NetDataWriter.html +++ b/docs/api/LiteNetLib.Utils.NetDataWriter.html @@ -1022,7 +1022,7 @@
    Parameters

    Put(string, int)

    -

    Serializes a string using a 2-byte float length header.

    +

    Serializes a string using a 2-byte ushort length header.

    Declaration
    diff --git a/docs/api/LiteNetLib.Utils.NetPacketProcessor.html b/docs/api/LiteNetLib.Utils.NetPacketProcessor.html index 8e539bf5..b80de24b 100644 --- a/docs/api/LiteNetLib.Utils.NetPacketProcessor.html +++ b/docs/api/LiteNetLib.Utils.NetPacketProcessor.html @@ -549,7 +549,8 @@
    Type Parameters

    SubscribeNetSerializable<T>(Action<T>)

    -
    +

    Registers a callback for a packet type that implements INetSerializable and has a parameterless constructor.

    +
    Declaration
    @@ -568,7 +569,8 @@
    Parameters
    Action<T> onReceive - +

    The delegate to be executed when the packet is received.

    + @@ -583,15 +585,20 @@
    Type Parameters
    T - +

    The type of the packet. Must implement INetSerializable and have a new() constraint.

    + +
    Remarks
    +

    To reduce allocations, this method uses a single internal reference to T for deserialization.

    +

    SubscribeNetSerializable<T>(Action<T>, Func<T>)

    -
    +

    Registers a callback for a packet type that implements INetSerializable, using a custom constructor.

    +
    Declaration
    @@ -610,12 +617,14 @@
    Parameters
    Action<T> onReceive - +

    The delegate to be executed when the packet is received.

    + Func<T> packetConstructor - +

    A function that returns a new instance of T.

    + @@ -630,7 +639,8 @@
    Type Parameters
    T - +

    The type of the packet. Must implement INetSerializable.

    + @@ -638,7 +648,8 @@
    Type Parameters

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>)

    -
    +

    Registers a callback for a packet type that implements INetSerializable and has a parameterless constructor, supporting user data.

    +
    Declaration
    @@ -657,7 +668,8 @@
    Parameters
    Action<T, TUserData> onReceive - +

    The delegate to be executed when the packet is received.

    + @@ -672,19 +684,25 @@
    Type Parameters
    T - +

    The type of the packet. Must implement INetSerializable and have a new() constraint.

    + TUserData - +

    The type of the user data (typically NetPeer).

    + +
    Remarks
    +

    To reduce allocations, this method uses a single internal reference to T for deserialization.

    +

    SubscribeNetSerializable<T, TUserData>(Action<T, TUserData>, Func<T>)

    -
    +

    Registers a callback for a packet type that implements INetSerializable, using a custom constructor and supporting user data.

    +
    Declaration
    @@ -703,12 +721,14 @@
    Parameters
    Action<T, TUserData> onReceive - +

    The delegate to be executed when the packet is received.

    + Func<T> packetConstructor - +

    A function that returns a new instance of T.

    + @@ -723,11 +743,13 @@
    Type Parameters
    T - +

    The type of the packet. Must implement INetSerializable.

    + TUserData - +

    The type of the user data (typically NetPeer).

    + diff --git a/docs/api/LiteNetLib.Utils.html b/docs/api/LiteNetLib.Utils.html index 6e58066d..344fbc61 100644 --- a/docs/api/LiteNetLib.Utils.html +++ b/docs/api/LiteNetLib.Utils.html @@ -101,7 +101,8 @@

    Interfaces

    INetSerializable

    -
    +

    Interface for implementing custom data serialization for network transmission.

    +

    Enums

    diff --git a/docs/api/LiteNetLib.html b/docs/api/LiteNetLib.html index 842b779e..323dc0da 100644 --- a/docs/api/LiteNetLib.html +++ b/docs/api/LiteNetLib.html @@ -81,7 +81,8 @@

    EventBasedL

    Simple event based listener for simple setups and benchmarks

    EventBasedNatPunchListener

    -
    +

    An implementation of INatPunchListener that maps callbacks to events.

    +

    EventBasedNetListener

    Simple event based listener for simple setups and benchmarks

    @@ -119,7 +120,8 @@

    NetPeer

    Improved LiteNetPeer with full multi-channel support

    NetStatistics

    -
    +

    Thread-safe counter for network statistics including sent/received packets, bytes, and packet loss.

    +

    NetUtils

    Some specific network utilities

    @@ -142,7 +144,8 @@

    ILiteNetEventLi

    Interface for implementing own ILiteNetEventListener. This is a bit faster than use EventBasedListener

    INatPunchListener

    -
    +

    Interface for handling events related to NAT punchthrough and introduction.

    +

    INetEventListener

    Interface for implementing own INetEventListener. This is a bit faster than use EventBasedListener

    @@ -165,9 +168,11 @@

    LocalAddrType

    Address type that you want to receive from NetUtils.GetLocalIp method

    NatAddressType

    -
    +

    Specifies the type of network address discovered during NAT punchthrough.

    +

    NetEvent.EType

    -
    +

    Specifies the category of the network event.

    +

    NetLogLevel

    UnconnectedMessageType

    diff --git a/docs/manifest.json b/docs/manifest.json index 09864182..3d87716c 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -98,7 +98,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.EventBasedNatPunchListener", - "Summary": null + "Summary": "

    An implementation of that maps callbacks to events.

    \n" }, { "type": "ManagedReference", @@ -140,7 +140,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.INatPunchListener", - "Summary": null + "Summary": "

    Interface for handling events related to NAT punchthrough and introduction.

    \n" }, { "type": "ManagedReference", @@ -336,7 +336,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.NatAddressType", - "Summary": null + "Summary": "

    Specifies the type of network address discovered during NAT punchthrough.

    \n" }, { "type": "ManagedReference", @@ -406,7 +406,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.NetEvent.EType", - "Summary": null + "Summary": "

    Specifies the category of the network event.

    \n" }, { "type": "ManagedReference", @@ -490,7 +490,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.NetStatistics", - "Summary": null + "Summary": "

    Thread-safe counter for network statistics including sent/received packets, bytes, and packet loss.

    \n" }, { "type": "ManagedReference", @@ -588,7 +588,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.Utils.INetSerializable", - "Summary": null + "Summary": "

    Interface for implementing custom data serialization for network transmission.

    \n" }, { "type": "ManagedReference", @@ -728,7 +728,7 @@ "Uid": null, "IsMRef": true, "Title": "LiteNetLib.Utils.PreserveAttribute", - "Summary": "

    PreserveAttribute prevents byte code stripping from removing a class, method, field, or property.

    \n" + "Summary": "

    PreserveAttribute prevents byte code stripping from removing a class, method, field, or property.

    \n" }, { "type": "ManagedReference", From baf4601f87462c987593e72819a38f7dec463bb3 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Wed, 25 Mar 2026 23:03:49 +0200 Subject: [PATCH 188/200] version 2.1.2 --- .github/workflows/nuget-publish.yml | 4 ++-- LiteNetLib/LiteNetLib.csproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/nuget-publish.yml b/.github/workflows/nuget-publish.yml index a963bc33..fd5ee070 100644 --- a/.github/workflows/nuget-publish.yml +++ b/.github/workflows/nuget-publish.yml @@ -33,10 +33,10 @@ jobs: PACKAGE_NAME="litenetlib" # Extract version from project file - LOCAL_VERSION=$(grep -o '[^<]*' "$PROJECT_PATH" | sed 's/\(.*\)<\/Version>/\1/') + LOCAL_VERSION=$(grep -o '[^<]*' "$PROJECT_PATH" | sed 's/\(.*\)<\/PackageVersion>/\1/') if [ -z "$LOCAL_VERSION" ]; then - echo "No tag found in $PROJECT_PATH" + echo "No tag found in $PROJECT_PATH" echo "has_packages=false" >> $GITHUB_OUTPUT exit 0 fi diff --git a/LiteNetLib/LiteNetLib.csproj b/LiteNetLib/LiteNetLib.csproj index e53cde48..856206b5 100644 --- a/LiteNetLib/LiteNetLib.csproj +++ b/LiteNetLib/LiteNetLib.csproj @@ -10,11 +10,11 @@ true 1701;1702;1705;1591 - 2.1.0 + 2.1.2 Lite reliable UDP library for Mono and .NET true true - 2.1.0 + 2.1.2 @@ -33,7 +33,7 @@ true $(DefineConstants);LITENETLIB_UNSAFE udp reliable-udp network - https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.0 + https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.2 git https://github.com/RevenantX/LiteNetLib https://github.com/RevenantX/LiteNetLib From 55f1d306dcb988c7bddd6bfe52e48d3bcd5d2447 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Fri, 27 Mar 2026 16:37:18 +0200 Subject: [PATCH 189/200] add MaxPacketPerManualReceive option and fix macos manual mode (cherry picked from commit e2de9ed52bfc576434634c9980d99f46f67fd01b) --- LiteNetLib/LiteNetManager.Socket.cs | 11 ++++++++--- LiteNetLib/LiteNetManager.cs | 6 ++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index 522e86a0..2f1e35a3 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -101,9 +101,14 @@ private void ManualReceive(Socket socket, EndPoint bufferEndPoint) //Reading data try { - int available = socket.Available; - while (available > 0) - available -= ReceiveFrom(socket, ref bufferEndPoint); + int count = MaxPacketPerManualReceive; + while (socket.Available > 0 && (count > 0 || MaxPacketPerManualReceive == 0)) + { + if(ReceiveFrom(socket, ref bufferEndPoint) > 0) + count--; + else + break; + } } catch (SocketException ex) { diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 5769b888..2903e8d8 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -269,6 +269,12 @@ private struct OutboundDelayedPacket ///
    public int ConnectedPeersCount => (int)Interlocked.Read(ref _connectedPeersCount); + /// + /// Maximum packets that can be received per one ManualReceive (PollEvents when started using StartInManualMode) + /// 0 - infinite - but this can cause some big delays there is too many incoming packets + /// + public int MaxPacketPerManualReceive = 256; + /// /// Gets the additional size in bytes required by the active . /// From 8c6300bc9001d5a2184c03b49ff9397c51186436 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Fri, 27 Mar 2026 17:04:22 +0200 Subject: [PATCH 190/200] add advance (default true) argument for GetRemainingBytes for some use cases --- LiteNetLib/Utils/NetDataReader.cs | 70 +++++++++++++++++-------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 6ab35568..230f3df4 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -541,69 +541,53 @@ public ArraySegment GetBytesSegment(int count) /// /// Gets an containing all remaining s. /// + /// advance position after call /// An from the current position to the end of the data. - public ArraySegment GetRemainingBytesSegment() + public ArraySegment GetRemainingBytesSegment(bool advance = true) { ArraySegment segment = new ArraySegment(_data, _position, AvailableBytes); - _position = _dataSize; + if(advance) + _position = _dataSize; return segment; } - /// - /// Deserializes a that implements . - /// - /// A type implementing . - /// The deserialized . - public T Get() where T : struct, INetSerializable - { - Get(out T result); - return result; - } - - /// - /// Deserializes a that implements using a provided constructor. - /// - /// A type implementing . - /// The factory used to instantiate the . - /// A new instance of . - public T Get(Func constructor) where T : class, INetSerializable - { - Get(out T result, constructor); - return result; - } - /// /// Returns a of s containing all remaining data. /// + /// advance position after call /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetRemainingBytesSpan() + public ReadOnlySpan GetRemainingBytesSpan(bool advance = true) { var result = new ReadOnlySpan(_data, _position, AvailableBytes); - _position = _dataSize; + if(advance) + _position = _dataSize; return result; } /// /// Returns a of s containing all remaining data. /// + /// advance position after call /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory GetRemainingBytesMemory() + public ReadOnlyMemory GetRemainingBytesMemory(bool advance = true) { var result = new ReadOnlyMemory(_data, _position, AvailableBytes); - _position = _dataSize; + if(advance) + _position = _dataSize; return result; } /// /// Reads all remaining s and returns them as a new array. /// + /// advance position after call /// A new array containing the remaining data. /// /// This method performs a heap allocation and advances the to the end of the data. /// - public byte[] GetRemainingBytes() + public byte[] GetRemainingBytes(bool advance = true) { int size = _dataSize - _position; if (size == 0) @@ -611,7 +595,31 @@ public byte[] GetRemainingBytes() byte[] result = new byte[size]; Buffer.BlockCopy(_data, _position, result, 0, size); - _position = _dataSize; + if(advance) + _position = _dataSize; + return result; + } + + /// + /// Deserializes a that implements . + /// + /// A type implementing . + /// The deserialized . + public T Get() where T : struct, INetSerializable + { + Get(out T result); + return result; + } + + /// + /// Deserializes a that implements using a provided constructor. + /// + /// A type implementing . + /// The factory used to instantiate the . + /// A new instance of . + public T Get(Func constructor) where T : class, INetSerializable + { + Get(out T result, constructor); return result; } From b691c7fdf351e9b2843f4e871f03966ec3d65a65 Mon Sep 17 00:00:00 2001 From: Lacyway <20912169+Lacyway@users.noreply.github.com> Date: Fri, 27 Mar 2026 17:11:14 +0100 Subject: [PATCH 191/200] Update methods to stay more consistent with rest of API --- LiteNetLib/Utils/NetDataReader.cs | 62 +++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 16 deletions(-) diff --git a/LiteNetLib/Utils/NetDataReader.cs b/LiteNetLib/Utils/NetDataReader.cs index 230f3df4..2e230009 100644 --- a/LiteNetLib/Utils/NetDataReader.cs +++ b/LiteNetLib/Utils/NetDataReader.cs @@ -541,53 +541,46 @@ public ArraySegment GetBytesSegment(int count) /// /// Gets an containing all remaining s. /// - /// advance position after call /// An from the current position to the end of the data. - public ArraySegment GetRemainingBytesSegment(bool advance = true) + public ArraySegment GetRemainingBytesSegment() { ArraySegment segment = new ArraySegment(_data, _position, AvailableBytes); - if(advance) - _position = _dataSize; + _position = _dataSize; return segment; } /// /// Returns a of s containing all remaining data. /// - /// advance position after call /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlySpan GetRemainingBytesSpan(bool advance = true) + public ReadOnlySpan GetRemainingBytesSpan() { var result = new ReadOnlySpan(_data, _position, AvailableBytes); - if(advance) - _position = _dataSize; + _position = _dataSize; return result; } /// /// Returns a of s containing all remaining data. /// - /// advance position after call /// A from the current to the end of the buffer. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ReadOnlyMemory GetRemainingBytesMemory(bool advance = true) + public ReadOnlyMemory GetRemainingBytesMemory() { var result = new ReadOnlyMemory(_data, _position, AvailableBytes); - if(advance) - _position = _dataSize; + _position = _dataSize; return result; } /// /// Reads all remaining s and returns them as a new array. /// - /// advance position after call /// A new array containing the remaining data. /// /// This method performs a heap allocation and advances the to the end of the data. /// - public byte[] GetRemainingBytes(bool advance = true) + public byte[] GetRemainingBytes() { int size = _dataSize - _position; if (size == 0) @@ -595,8 +588,7 @@ public byte[] GetRemainingBytes(bool advance = true) byte[] result = new byte[size]; Buffer.BlockCopy(_data, _position, result, 0, size); - if(advance) - _position = _dataSize; + _position = _dataSize; return result; } @@ -809,6 +801,44 @@ public unsafe T PeekUnmanaged() where T : unmanaged #endif } + /// + /// Returns a of s containing all remaining data without advancing the reader . + /// + /// A from the current to the end of the buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlySpan PeekRemainingBytesSpan() + { + return new ReadOnlySpan(_data, _position, AvailableBytes); + } + + /// + /// Returns a of s containing all remaining data without advancing the reader . + /// + /// A from the current to the end of the buffer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ReadOnlyMemory PeekRemainingBytesMemory() + { + return new ReadOnlyMemory(_data, _position, AvailableBytes); + } + + /// + /// Reads all remaining s and returns them as a new array without advancing the reader . + /// + /// A new array containing the remaining data. + /// + /// This method performs a heap allocation by copying the data into a new array. + /// + public byte[] PeekRemainingBytes() + { + int size = _dataSize - _position; + if (size == 0) + return Array.Empty(); + + byte[] result = new byte[size]; + Buffer.BlockCopy(_data, _position, result, 0, size); + return result; + } + #endregion #region TryGetMethods From 329b16c1423db86bd64deead216afbab0cd972c6 Mon Sep 17 00:00:00 2001 From: Stiefel Jackal Date: Wed, 15 Apr 2026 22:11:58 -0500 Subject: [PATCH 192/200] fix(LiteNetPeer): get packets count in reliable unordered channel --- LiteNetLib/LiteNetPeer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index fd4cc561..78ba2e9d 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -339,7 +339,7 @@ private void OverrideMtu(int mtuValue) /// type of channel ReliableOrdered or ReliableUnordered /// packets count in channel queue public int GetPacketsCountInReliableQueue(bool ordered) => - _reliableChannel?.PacketsInQueue ?? 0; + (ordered ? _reliableChannel : _reliableUnorderedChannel)?.PacketsInQueue ?? 0; /// /// Create temporary packet (maximum size MTU - headerSize) to send later without additional copies From ef66d4fbff11783c6662729801548fc28cc2e402 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Sat, 18 Apr 2026 09:30:51 +0300 Subject: [PATCH 193/200] Add GetPacketsCountInReliableQueue new method for NetPeer --- LiteNetLib/NetPeer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/LiteNetLib/NetPeer.cs b/LiteNetLib/NetPeer.cs index fcc304c5..3be8844e 100644 --- a/LiteNetLib/NetPeer.cs +++ b/LiteNetLib/NetPeer.cs @@ -195,6 +195,14 @@ public int GetPacketsCountInReliableQueue(byte channelNumber, bool ordered) return ((ReliableChannel)_channels[idx])?.PacketsInQueue ?? 0; } + /// + /// Returns packets count in queue for reliable channel 0 + /// + /// type of channel ReliableOrdered or ReliableUnordered + /// packets count in channel queue + public new int GetPacketsCountInReliableQueue(bool ordered) => + GetPacketsCountInReliableQueue(0, ordered); + protected override void UpdateChannels() { //Pending send From ed6ac2e8384d76f76c5f56d85bd558cb9a9f4618 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Sat, 18 Apr 2026 09:31:41 +0300 Subject: [PATCH 194/200] 2.1.3 and docs --- LiteNetLib/LiteNetLib.csproj | 6 +- docs/api/LiteNetLib.LiteNetManager.html | 26 ++++++ docs/api/LiteNetLib.NetManager.html | 3 + docs/api/LiteNetLib.NetPacketReader.html | 19 +++-- docs/api/LiteNetLib.NetPeer.html | 48 ++++++++++- docs/api/LiteNetLib.Utils.NetDataReader.html | 84 ++++++++++++++++++++ docs/xrefmap.yml | 54 +++++++++++++ 7 files changed, 229 insertions(+), 11 deletions(-) diff --git a/LiteNetLib/LiteNetLib.csproj b/LiteNetLib/LiteNetLib.csproj index 856206b5..fa18ce06 100644 --- a/LiteNetLib/LiteNetLib.csproj +++ b/LiteNetLib/LiteNetLib.csproj @@ -10,11 +10,11 @@ true 1701;1702;1705;1591 - 2.1.2 + 2.1.3 Lite reliable UDP library for Mono and .NET true true - 2.1.2 + 2.1.3 @@ -33,7 +33,7 @@ true $(DefineConstants);LITENETLIB_UNSAFE udp reliable-udp network - https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.2 + https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.3 git https://github.com/RevenantX/LiteNetLib https://github.com/RevenantX/LiteNetLib diff --git a/docs/api/LiteNetLib.LiteNetManager.html b/docs/api/LiteNetLib.LiteNetManager.html index b687ab16..96542635 100644 --- a/docs/api/LiteNetLib.LiteNetManager.html +++ b/docs/api/LiteNetLib.LiteNetManager.html @@ -409,6 +409,32 @@
    Field Value
    +

    MaxPacketPerManualReceive

    +

    Maximum packets that can be received per one ManualReceive (PollEvents when started using StartInManualMode) +0 - infinite - but this can cause some big delays there is too many incoming packets

    +
    +
    +
    Declaration
    +
    +
    public int MaxPacketPerManualReceive
    +
    +
    Field Value
    + + + + + + + + + + + + + +
    TypeDescription
    int
    + +

    MtuDiscovery

    Automatically discovery mtu starting from. Use at own risk because some routers can break MTU detection and connection in result

    diff --git a/docs/api/LiteNetLib.NetManager.html b/docs/api/LiteNetLib.NetManager.html index 86c94fa8..4e240dbe 100644 --- a/docs/api/LiteNetLib.NetManager.html +++ b/docs/api/LiteNetLib.NetManager.html @@ -184,6 +184,9 @@
    Inherited Members
    + diff --git a/docs/api/LiteNetLib.NetPacketReader.html b/docs/api/LiteNetLib.NetPacketReader.html index 9a8ae4b3..df51c9cb 100644 --- a/docs/api/LiteNetLib.NetPacketReader.html +++ b/docs/api/LiteNetLib.NetPacketReader.html @@ -277,19 +277,19 @@
    Inherited Members
    NetDataReader.GetRemainingBytesSegment()
    NetDataReader.GetBytes(byte[], int, int) @@ -357,6 +357,15 @@
    Inherited Members
    + + + diff --git a/docs/api/LiteNetLib.NetPeer.html b/docs/api/LiteNetLib.NetPeer.html index 45070f98..c8234ae8 100644 --- a/docs/api/LiteNetLib.NetPeer.html +++ b/docs/api/LiteNetLib.NetPeer.html @@ -132,9 +132,6 @@
    Inherited Members
    - @@ -298,6 +295,51 @@
    Returns
    + +

    GetPacketsCountInReliableQueue(bool)

    +

    Returns packets count in queue for reliable channel 0

    +
    +
    +
    Declaration
    +
    +
    public int GetPacketsCountInReliableQueue(bool ordered)
    +
    +
    Parameters
    + + + + + + + + + + + + + + + +
    TypeNameDescription
    boolordered

    type of channel ReliableOrdered or ReliableUnordered

    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    int

    packets count in channel queue

    +
    + +

    GetPacketsCountInReliableQueue(byte, bool)

    Returns packets count in queue for reliable channel

    diff --git a/docs/api/LiteNetLib.Utils.NetDataReader.html b/docs/api/LiteNetLib.Utils.NetDataReader.html index e12c546e..4b210e38 100644 --- a/docs/api/LiteNetLib.Utils.NetDataReader.html +++ b/docs/api/LiteNetLib.Utils.NetDataReader.html @@ -2791,6 +2791,90 @@
    Returns
    + +

    PeekRemainingBytes()

    +

    Reads all remaining bytes and returns them as a new array without advancing the reader _position.

    +
    +
    +
    Declaration
    +
    +
    public byte[] PeekRemainingBytes()
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    byte[]

    A new byte array containing the remaining data.

    +
    +
    Remarks
    +

    This method performs a heap allocation by copying the data into a new array.

    +
    + + + +

    PeekRemainingBytesMemory()

    +

    Returns a ReadOnlyMemory<T> of bytes containing all remaining data without advancing the reader _position.

    +
    +
    +
    Declaration
    +
    +
    public ReadOnlyMemory<byte> PeekRemainingBytesMemory()
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    ReadOnlyMemory<byte>

    A ReadOnlyMemory<T> from the current Position to the end of the buffer.

    +
    + + + +

    PeekRemainingBytesSpan()

    +

    Returns a ReadOnlySpan<T> of bytes containing all remaining data without advancing the reader _position.

    +
    +
    +
    Declaration
    +
    +
    public ReadOnlySpan<byte> PeekRemainingBytesSpan()
    +
    +
    Returns
    + + + + + + + + + + + + + +
    TypeDescription
    ReadOnlySpan<byte>

    A ReadOnlySpan<T> from the current Position to the end of the buffer.

    +
    + +

    PeekSByte()

    Reads the sbyte at the current position without advancing the Position.

    diff --git a/docs/xrefmap.yml b/docs/xrefmap.yml index 3dde95bc..02999b85 100644 --- a/docs/xrefmap.yml +++ b/docs/xrefmap.yml @@ -1789,6 +1789,12 @@ references: commentId: F:LiteNetLib.LiteNetManager.MaxFragmentsCount fullName: LiteNetLib.LiteNetManager.MaxFragmentsCount nameWithType: LiteNetManager.MaxFragmentsCount +- uid: LiteNetLib.LiteNetManager.MaxPacketPerManualReceive + name: MaxPacketPerManualReceive + href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_MaxPacketPerManualReceive + commentId: F:LiteNetLib.LiteNetManager.MaxPacketPerManualReceive + fullName: LiteNetLib.LiteNetManager.MaxPacketPerManualReceive + nameWithType: LiteNetManager.MaxPacketPerManualReceive - uid: LiteNetLib.LiteNetManager.MtuDiscovery name: MtuDiscovery href: api/LiteNetLib.LiteNetManager.html#LiteNetLib_LiteNetManager_MtuDiscovery @@ -3715,6 +3721,15 @@ references: isSpec: "True" fullName: LiteNetLib.NetPeer.CreatePacketFromPool nameWithType: NetPeer.CreatePacketFromPool +- uid: LiteNetLib.NetPeer.GetPacketsCountInReliableQueue(System.Boolean) + name: GetPacketsCountInReliableQueue(bool) + href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_GetPacketsCountInReliableQueue_System_Boolean_ + commentId: M:LiteNetLib.NetPeer.GetPacketsCountInReliableQueue(System.Boolean) + name.vb: GetPacketsCountInReliableQueue(Boolean) + fullName: LiteNetLib.NetPeer.GetPacketsCountInReliableQueue(bool) + fullName.vb: LiteNetLib.NetPeer.GetPacketsCountInReliableQueue(Boolean) + nameWithType: NetPeer.GetPacketsCountInReliableQueue(bool) + nameWithType.vb: NetPeer.GetPacketsCountInReliableQueue(Boolean) - uid: LiteNetLib.NetPeer.GetPacketsCountInReliableQueue(System.Byte,System.Boolean) name: GetPacketsCountInReliableQueue(byte, bool) href: api/LiteNetLib.NetPeer.html#LiteNetLib_NetPeer_GetPacketsCountInReliableQueue_System_Byte_System_Boolean_ @@ -5251,6 +5266,45 @@ references: isSpec: "True" fullName: LiteNetLib.Utils.NetDataReader.PeekLong nameWithType: NetDataReader.PeekLong +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytes + name: PeekRemainingBytes() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytes + commentId: M:LiteNetLib.Utils.NetDataReader.PeekRemainingBytes + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytes() + nameWithType: NetDataReader.PeekRemainingBytes() +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytes* + name: PeekRemainingBytes + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytes_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.PeekRemainingBytes + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytes + nameWithType: NetDataReader.PeekRemainingBytes +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory + name: PeekRemainingBytesMemory() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytesMemory + commentId: M:LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory() + nameWithType: NetDataReader.PeekRemainingBytesMemory() +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory* + name: PeekRemainingBytesMemory + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytesMemory_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesMemory + nameWithType: NetDataReader.PeekRemainingBytesMemory +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan + name: PeekRemainingBytesSpan() + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytesSpan + commentId: M:LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan() + nameWithType: NetDataReader.PeekRemainingBytesSpan() +- uid: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan* + name: PeekRemainingBytesSpan + href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekRemainingBytesSpan_ + commentId: Overload:LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan + isSpec: "True" + fullName: LiteNetLib.Utils.NetDataReader.PeekRemainingBytesSpan + nameWithType: NetDataReader.PeekRemainingBytesSpan - uid: LiteNetLib.Utils.NetDataReader.PeekSByte name: PeekSByte() href: api/LiteNetLib.Utils.NetDataReader.html#LiteNetLib_Utils_NetDataReader_PeekSByte From 67e3d310b7b53b4b8fe1b461500cbfe56fdddbcd Mon Sep 17 00:00:00 2001 From: Kirill Artemov Date: Sun, 3 May 2026 18:46:57 +0200 Subject: [PATCH 195/200] Add NetManager.SendToAll overloads with ReadOnlySpan support --- LiteNetLib/NetManager.cs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/LiteNetLib/NetManager.cs b/LiteNetLib/NetManager.cs index 8ff80cfe..fc02a659 100644 --- a/LiteNetLib/NetManager.cs +++ b/LiteNetLib/NetManager.cs @@ -314,6 +314,39 @@ public void SendToAll(byte[] data, int start, int length, byte channelNumber, De } } + /// + /// Send data to all connected peers + /// + /// Data + /// Number of channel (from 0 to channelsCount - 1) + /// Send options (reliable, unreliable, etc.) + public void SendToAll(ReadOnlySpan data, byte channelNumber, DeliveryMethod options) => + SendToAll(data, channelNumber, options, null); + + /// + /// Send data to all connected peers + /// + /// Data + /// Number of channel (from 0 to channelsCount - 1) + /// Send options (reliable, unreliable, etc.) + /// Excluded peer + public void SendToAll(ReadOnlySpan data, byte channelNumber, DeliveryMethod options, LiteNetPeer excludePeer) + { + try + { + _peersLock.EnterReadLock(); + for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) + { + if (netPeer != excludePeer) + ((NetPeer)netPeer).Send(data, channelNumber, options); + } + } + finally + { + _peersLock.ExitReadLock(); + } + } + /// /// Connect to remote host /// From ae8ece75ee2c5014a46ebd641319eb4097c1e39d Mon Sep 17 00:00:00 2001 From: Ruslan Pyrch Date: Wed, 6 May 2026 10:08:02 +0300 Subject: [PATCH 196/200] Update README.md for LiteNetLib (fix #609) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a21898fd..85caa020 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ var listener = new EventBasedNetListener(); var client = new NetManager(listener); client.Start(); client.Connect("localhost" /* host IP or name */, 9050 /* port */, "SomeConnectionKey" /* text key or NetDataWriter */); -listener.NetworkReceiveEvent += (fromPeer, dataReader, deliveryMethod, channel) => +listener.NetworkReceiveEvent += (fromPeer, dataReader, channel, deliveryMethod) => { Console.WriteLine("We got: {0}", dataReader.GetString(100 /* max length of string */)); dataReader.Recycle(); From f9d506f26e5677a18a233f3612dedde3fd419dcd Mon Sep 17 00:00:00 2001 From: RevenantX Date: Tue, 19 May 2026 10:56:18 +0300 Subject: [PATCH 197/200] do not simulate outbound latency for disconnect message. Also optimize a bit SendRaw --- LiteNetLib/LiteNetManager.Socket.cs | 18 ++++-------------- LiteNetLib/LiteNetManager.cs | 27 +++++++++++++++++---------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/LiteNetLib/LiteNetManager.Socket.cs b/LiteNetLib/LiteNetManager.Socket.cs index 2f1e35a3..97d6870b 100644 --- a/LiteNetLib/LiteNetManager.Socket.cs +++ b/LiteNetLib/LiteNetManager.Socket.cs @@ -545,20 +545,10 @@ internal int SendRaw(byte[] message, int start, int length, IPEndPoint remoteEnd } #endif - return SendRawCoreWithCleanup(message, start, length, remoteEndPoint, expandedPacket); - } - - private int SendRawCoreWithCleanup(byte[] message, int start, int length, IPEndPoint remoteEndPoint, NetPacket expandedPacket) - { - try - { - return SendRawCore(message, start, length, remoteEndPoint); - } - finally - { - if (expandedPacket != null) - PoolRecycle(expandedPacket); - } + int result = SendRawCore(message, start, length, remoteEndPoint); + if (expandedPacket != null) + PoolRecycle(expandedPacket); + return result; } // Core socket sending logic without simulation - used by both SendRaw and delayed packet processing diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index 2903e8d8..d093accc 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -45,6 +45,7 @@ public void Reset() => object IEnumerator.Current => _p; } +#if DEBUG || SIMULATE_NETWORK private struct IncomingData { public NetPacket Data; @@ -53,7 +54,6 @@ private struct IncomingData } private readonly List _pingSimulationList = new List(); -#if DEBUG || SIMULATE_NETWORK private struct OutboundDelayedPacket { public byte[] Data; @@ -556,6 +556,7 @@ private void ProcessDelayedPackets() if (!SimulateLatency) return; +#if DEBUG || SIMULATE_NETWORK var time = DateTime.UtcNow; lock (_pingSimulationList) { @@ -571,7 +572,6 @@ private void ProcessDelayedPackets() } } -#if DEBUG || SIMULATE_NETWORK lock (_outboundSimulationList) { for (int i = 0; i < _outboundSimulationList.Count; i++) @@ -765,7 +765,7 @@ private void HandleSimulateLatency(NetPacket packet, IPEndPoint remoteEndPoint) { return; } - +#if DEBUG || SIMULATE_NETWORK int roundTripLatency = _randomGenerator.Next(SimulationMinLatency, SimulationMaxLatency); int inboundLatency = roundTripLatency / 2; if (inboundLatency > MinLatencyThreshold) @@ -782,6 +782,7 @@ private void HandleSimulateLatency(NetPacket packet, IPEndPoint remoteEndPoint) // hold packet _dropPacket = true; } +#endif } [Conditional("DEBUG"), Conditional("SIMULATE_NETWORK")] @@ -828,11 +829,8 @@ private bool HandleSimulateOutboundLatency(byte[] data, int start, int length, I #endif #if DEBUG || SIMULATE_NETWORK - private bool HandleSimulateOutboundPacketLoss() - { - bool shouldDrop = SimulatePacketLoss && _randomGenerator.NextDouble() * 100 < SimulationPacketLossChance; - return shouldDrop; - } + private bool HandleSimulateOutboundPacketLoss() => //Should Drop? + SimulatePacketLoss && _randomGenerator.NextDouble() * 100 < SimulationPacketLossChance; #endif internal virtual bool CustomMessageHandle(NetPacket packet, IPEndPoint remoteEndPoint) => @@ -1482,8 +1480,14 @@ public void Stop(bool sendDisconnectMessages) { if (!_isRunning) return; + NetDebug.Write("[NM] Stop"); + //Little hack so shutdown message will not be queued by Outbound latency simulation + //In real world packet will be delayed by routers not by application(that closes) logic + var simLat = SimulateLatency; + SimulateLatency = false; + //Send last disconnect for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) netPeer.Shutdown(null, 0, 0, !sendDisconnectMessages); @@ -1491,6 +1495,9 @@ public void Stop(bool sendDisconnectMessages) //Stop CloseSocket(); + //Return setting + SimulateLatency = simLat; + #if UNITY_SOCKET_FIX if (_useSocketFix) { @@ -1519,14 +1526,14 @@ public void Stop(bool sendDisconnectMessages) _pendingEventTail = null; } - [Conditional("DEBUG"), Conditional("SIMULATE_NETWORK")] private void ClearPingSimulationList() { +#if DEBUG || SIMULATE_NETWORK lock (_pingSimulationList) _pingSimulationList.Clear(); +#endif } - [Conditional("DEBUG"), Conditional("SIMULATE_NETWORK")] private void ClearOutboundSimulationList() { #if DEBUG || SIMULATE_NETWORK From 7949480c3d7677813f49d6bf6ac22aa64e503a49 Mon Sep 17 00:00:00 2001 From: RevenantX Date: Tue, 19 May 2026 10:58:28 +0300 Subject: [PATCH 198/200] simplify code --- LiteNetLib/LiteNetManager.cs | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index d093accc..f9ee0012 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -1518,28 +1518,16 @@ public void Stop(bool sendDisconnectMessages) _peerIds = new ConcurrentQueue(); _lastPeerId = 0; - ClearPingSimulationList(); - ClearOutboundSimulationList(); - - _connectedPeersCount = 0; - _pendingEventHead = null; - _pendingEventTail = null; - } - - private void ClearPingSimulationList() - { #if DEBUG || SIMULATE_NETWORK lock (_pingSimulationList) _pingSimulationList.Clear(); -#endif - } - - private void ClearOutboundSimulationList() - { -#if DEBUG || SIMULATE_NETWORK lock (_outboundSimulationList) _outboundSimulationList.Clear(); #endif + + _connectedPeersCount = 0; + _pendingEventHead = null; + _pendingEventTail = null; } /// From 4d3de1e93abaead30199bf572f4a3363f854e14b Mon Sep 17 00:00:00 2001 From: RevenantX Date: Tue, 19 May 2026 11:04:43 +0300 Subject: [PATCH 199/200] version 2.1.4 --- LiteNetLib/LiteNetLib.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LiteNetLib/LiteNetLib.csproj b/LiteNetLib/LiteNetLib.csproj index fa18ce06..1b1249b1 100644 --- a/LiteNetLib/LiteNetLib.csproj +++ b/LiteNetLib/LiteNetLib.csproj @@ -10,11 +10,11 @@ true 1701;1702;1705;1591 - 2.1.3 + 2.1.4 Lite reliable UDP library for Mono and .NET true true - 2.1.3 + 2.1.4 @@ -33,7 +33,7 @@ true $(DefineConstants);LITENETLIB_UNSAFE udp reliable-udp network - https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.3 + https://github.com/RevenantX/LiteNetLib/releases/tag/2.1.4 git https://github.com/RevenantX/LiteNetLib https://github.com/RevenantX/LiteNetLib From fedcaa013828b4c8057734aee02547b2a63d9ccd Mon Sep 17 00:00:00 2001 From: KingofBeast Date: Sun, 7 Jun 2026 00:01:53 -0500 Subject: [PATCH 200/200] Add ReadOnlySpan overloads to Reject/Disconnect methods --- LiteNetLib/ConnectionRequest.cs | 60 +++++++++++++++++++++++---------- LiteNetLib/LiteNetManager.cs | 53 ++++++++++++++++------------- LiteNetLib/LiteNetPeer.cs | 17 +++++----- 3 files changed, 82 insertions(+), 48 deletions(-) diff --git a/LiteNetLib/ConnectionRequest.cs b/LiteNetLib/ConnectionRequest.cs index 8fb15cf5..080009ab 100644 --- a/LiteNetLib/ConnectionRequest.cs +++ b/LiteNetLib/ConnectionRequest.cs @@ -1,4 +1,5 @@ -using System.Net; +using System; +using System.Net; using System.Threading; using LiteNetLib.Utils; @@ -76,10 +77,10 @@ public LiteNetPeer AcceptIfKey(string key) NetDebug.WriteError("[AC] Invalid incoming data"); } if (Result == ConnectionRequestResult.Accept) - return _listener.OnConnectionSolved(this, null, 0, 0); + return _listener.OnConnectionSolved(this, ReadOnlySpan.Empty); Result = ConnectionRequestResult.Reject; - _listener.OnConnectionSolved(this, null, 0, 0); + _listener.OnConnectionSolved(this, ReadOnlySpan.Empty); return null; } @@ -92,27 +93,38 @@ public LiteNetPeer Accept() if (!TryActivate()) return null; Result = ConnectionRequestResult.Accept; - return _listener.OnConnectionSolved(this, null, 0, 0); + return _listener.OnConnectionSolved(this, ReadOnlySpan.Empty); } /// /// Rejects the connection request. /// /// Optional user data to send along with the rejection packet. - /// Offset in the array. - /// Length of the data to be sent from the array. /// - /// If , immediately removes the request, if is not a reject packet is also sent.
    + /// If , immediately removes the request, if is not empty a reject packet is also sent.
    /// If , creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets. /// - public void Reject(byte[] rejectData, int start, int length, bool force) + public void Reject(ReadOnlySpan rejectData, bool force) { if (!TryActivate()) return; Result = force ? ConnectionRequestResult.RejectForce : ConnectionRequestResult.Reject; - _listener.OnConnectionSolved(this, rejectData, start, length); + _listener.OnConnectionSolved(this, rejectData); } + /// + /// Rejects the connection request. + /// + /// Optional user data to send along with the rejection packet. + /// Offset in the array. + /// Length of the data to be sent from the array. + /// + /// If , immediately removes the request, if is not a reject packet is also sent.
    + /// If , creates a temporary peer that sends rejection packets and lingers in memory until a timeout occurs to handle late-arriving packets. + /// + public void Reject(byte[] rejectData, int start, int length, bool force) => + Reject(new ReadOnlySpan(rejectData, start, length), force); + /// /// Rejects the connection reliably. Creates a temporary peer to handle packet loss. /// @@ -120,7 +132,7 @@ public void Reject(byte[] rejectData, int start, int length, bool force) /// Offset in the array. /// Length of the data to be sent. public void Reject(byte[] rejectData, int start, int length) => - Reject(rejectData, start, length, false); + Reject(new ReadOnlySpan(rejectData, start, length), false); /// /// Rejects the connection immediately without reliability. @@ -130,47 +142,61 @@ public void Reject(byte[] rejectData, int start, int length) => /// Offset in the array. /// Length of the data to be sent. public void RejectForce(byte[] rejectData, int start, int length) => - Reject(rejectData, start, length, true); + Reject(new ReadOnlySpan(rejectData, start, length), true); /// /// Rejects the connection immediately without sending any packet. /// public void RejectForce() => - Reject(null, 0, 0, true); + Reject(ReadOnlySpan.Empty, true); /// /// Rejects the connection immediately without reliability. /// /// Data to send with the rejection. public void RejectForce(byte[] rejectData) => - Reject(rejectData, 0, rejectData.Length, true); + Reject(new ReadOnlySpan(rejectData), true); /// /// Rejects the connection immediately without reliability using data from a . /// /// Writer containing the data to send. public void RejectForce(NetDataWriter rejectData) => - Reject(rejectData.Data, 0, rejectData.Length, true); + Reject(rejectData.AsReadOnlySpan(), true); + + /// + /// Rejects the connection immediately without reliability. + /// + /// Data to send with the rejection. + public void RejectForce(ReadOnlySpan rejectData) => + Reject(rejectData, true); /// /// Rejects the connection reliably without additional data. /// public void Reject() => - Reject(null, 0, 0, false); + Reject(ReadOnlySpan.Empty, false); /// /// Rejects the connection reliably. /// /// Data to send with the rejection. public void Reject(byte[] rejectData) => - Reject(rejectData, 0, rejectData.Length, false); + Reject(new ReadOnlySpan(rejectData), false); /// /// Rejects the connection reliably using data from a . /// /// Writer containing the data to send. public void Reject(NetDataWriter rejectData) => - Reject(rejectData.Data, 0, rejectData.Length, false); + Reject(rejectData.AsReadOnlySpan(), false); + + /// + /// Rejects the connection reliably. + /// + /// Data to send with the rejection. + public void Reject(ReadOnlySpan rejectData) => + Reject(rejectData, false); } public class ConnectionRequest : LiteConnectionRequest diff --git a/LiteNetLib/LiteNetManager.cs b/LiteNetLib/LiteNetManager.cs index f9ee0012..3d173ce7 100644 --- a/LiteNetLib/LiteNetManager.cs +++ b/LiteNetLib/LiteNetManager.cs @@ -313,7 +313,7 @@ internal void DisconnectPeerForce(LiteNetPeer peer, DisconnectReason reason, SocketError socketErrorCode, NetPacket eventData) => - DisconnectPeer(peer, reason, socketErrorCode, true, null, 0, 0, eventData); + DisconnectPeer(peer, reason, socketErrorCode, true, ReadOnlySpan.Empty, eventData); /// /// Disconnects a peer and handles internal state cleanup. @@ -327,20 +327,16 @@ internal void DisconnectPeerForce(LiteNetPeer peer, /// Peer will linger until to ignore late-arriving packets from the old session. /// /// Optional custom data to include in the disconnect packet. - /// Offset in the array. - /// Number of bytes to send from the array. /// Internal packet data associated with the disconnect event. private void DisconnectPeer( LiteNetPeer peer, DisconnectReason reason, SocketError socketErrorCode, bool force, - byte[] data, - int start, - int count, + ReadOnlySpan data, NetPacket eventData) { - var shutdownResult = peer.Shutdown(data, start, count, force); + var shutdownResult = peer.Shutdown(data, force); if (shutdownResult == ShutdownResult.None) return; if (shutdownResult == ShutdownResult.WasConnected) @@ -631,22 +627,22 @@ protected virtual LiteNetPeer CreateRejectPeer(IPEndPoint remoteEndPoint, int id protected virtual LiteConnectionRequest CreateConnectionRequest(IPEndPoint remoteEndPoint, NetConnectRequestPacket requestPacket) => new LiteConnectionRequest(remoteEndPoint, requestPacket, this); - internal LiteNetPeer OnConnectionSolved(LiteConnectionRequest request, byte[] rejectData, int start, int length) + internal LiteNetPeer OnConnectionSolved(LiteConnectionRequest request, ReadOnlySpan rejectData) { LiteNetPeer netPeer = null; if (request.Result == ConnectionRequestResult.RejectForce) { NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject force."); - if (rejectData != null && length > 0) + if (!rejectData.IsEmpty) { - var shutdownPacket = PoolGetWithProperty(PacketProperty.Disconnect, length); + var shutdownPacket = PoolGetWithProperty(PacketProperty.Disconnect, rejectData.Length); shutdownPacket.ConnectionNumber = request.InternalPacket.ConnectionNumber; FastBitConverter.GetBytes(shutdownPacket.RawData, 1, request.InternalPacket.ConnectionTime); if (shutdownPacket.Size >= NetConstants.PossibleMtu[0]) NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU!"); else - Buffer.BlockCopy(rejectData, start, shutdownPacket.RawData, 9, length); + rejectData.CopyTo(shutdownPacket.RawData.AsSpan(9)); SendRawAndRecycle(shutdownPacket, request.RemoteEndPoint); } lock (_requestsDict) @@ -661,7 +657,7 @@ internal LiteNetPeer OnConnectionSolved(LiteConnectionRequest request, byte[] re else if (request.Result == ConnectionRequestResult.Reject) { netPeer = CreateRejectPeer(request.RemoteEndPoint, GetNextPeerId()); - netPeer.Reject(request.InternalPacket, rejectData, start, length); + netPeer.Reject(request.InternalPacket, rejectData); AddPeer(netPeer); NetDebug.Write(NetLogLevel.Trace, "[NM] Peer connect reject."); } @@ -1490,7 +1486,7 @@ public void Stop(bool sendDisconnectMessages) //Send last disconnect for (var netPeer = _headPeer; netPeer != null; netPeer = netPeer.NextPeer) - netPeer.Shutdown(null, 0, 0, !sendDisconnectMessages); + netPeer.Shutdown(ReadOnlySpan.Empty, !sendDisconnectMessages); //Stop CloseSocket(); @@ -1576,7 +1572,7 @@ public void GetConnectedPeers(List peers) => /// Disconnect all peers without any additional data /// public void DisconnectAll() => - DisconnectAll(null, 0, 0); + DisconnectAll(ReadOnlySpan.Empty); /// /// Disconnect all peers with shutdown message @@ -1584,7 +1580,14 @@ public void DisconnectAll() => /// Data to send (must be less or equal MTU) /// Data start /// Data count - public void DisconnectAll(byte[] data, int start, int count) + public void DisconnectAll(byte[] data, int start, int count) => + DisconnectAll(new ReadOnlySpan(data, start, count)); + + /// + /// Disconnect all peers with shutdown message + /// + /// Data to send (must be less or equal MTU) + public void DisconnectAll(ReadOnlySpan data) { //Send disconnect packets _peersLock.EnterReadLock(); @@ -1596,8 +1599,6 @@ public void DisconnectAll(byte[] data, int start, int count) 0, false, data, - start, - count, null); } _peersLock.ExitReadLock(); @@ -1615,7 +1616,7 @@ public void DisconnectPeerForce(LiteNetPeer peer) => /// /// peer to disconnect public void DisconnectPeer(LiteNetPeer peer) => - DisconnectPeer(peer, null, 0, 0); + DisconnectPeer(peer, ReadOnlySpan.Empty); /// /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) @@ -1623,7 +1624,7 @@ public void DisconnectPeer(LiteNetPeer peer) => /// peer to disconnect /// additional data public void DisconnectPeer(LiteNetPeer peer, byte[] data) => - DisconnectPeer(peer, data, 0, data.Length); + DisconnectPeer(peer, new ReadOnlySpan(data)); /// /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) @@ -1631,7 +1632,7 @@ public void DisconnectPeer(LiteNetPeer peer, byte[] data) => /// peer to disconnect /// additional data public void DisconnectPeer(LiteNetPeer peer, NetDataWriter writer) => - DisconnectPeer(peer, writer.Data, 0, writer.Length); + DisconnectPeer(peer, writer.AsReadOnlySpan()); /// /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) @@ -1640,7 +1641,15 @@ public void DisconnectPeer(LiteNetPeer peer, NetDataWriter writer) => /// additional data /// data start /// data length - public void DisconnectPeer(LiteNetPeer peer, byte[] data, int start, int count) + public void DisconnectPeer(LiteNetPeer peer, byte[] data, int start, int count) => + DisconnectPeer(peer, new ReadOnlySpan(data, start, count)); + + /// + /// Disconnect peer from server and send additional data (Size must be less or equal MTU - 8) + /// + /// peer to disconnect + /// additional data + public void DisconnectPeer(LiteNetPeer peer, ReadOnlySpan data) { DisconnectPeer( peer, @@ -1648,8 +1657,6 @@ public void DisconnectPeer(LiteNetPeer peer, byte[] data, int start, int count) 0, false, data, - start, - count, null); } diff --git a/LiteNetLib/LiteNetPeer.cs b/LiteNetLib/LiteNetPeer.cs index 78ba2e9d..f36796c3 100644 --- a/LiteNetLib/LiteNetPeer.cs +++ b/LiteNetLib/LiteNetPeer.cs @@ -446,11 +446,11 @@ internal LiteNetPeer(LiteNetManager netManager, LiteConnectionRequest request, i } //Reject - internal void Reject(NetConnectRequestPacket requestData, byte[] data, int start, int length) + internal void Reject(NetConnectRequestPacket requestData, ReadOnlySpan data) { _connectTime = requestData.ConnectionTime; _connectNum = requestData.ConnectionNumber; - Shutdown(data, start, length, false); + Shutdown(data, false); } internal bool ProcessConnectAccept(NetConnectAcceptPacket packet) @@ -698,6 +698,9 @@ public void Disconnect(NetDataWriter writer) => public void Disconnect(byte[] data, int start, int count) => NetManager.DisconnectPeer(this, data, start, count); + public void Disconnect(ReadOnlySpan data) => + NetManager.DisconnectPeer(this, data); + public void Disconnect() => NetManager.DisconnectPeer(this); @@ -724,15 +727,13 @@ internal virtual void AddToReliableChannelSendQueue(BaseChannel channel) /// Internally handles the shutdown process for this peer. /// /// Optional data to include in the unreliable disconnect packet. - /// Offset in the array. - /// Length of the data to send. /// /// If , immediately sets state to without sending a notification.
    /// If , sends unreliable disconnect packets until a timeout occurs and sets state to /// Queued reliable packets are bypassed and dropped immediately. /// /// A indicating the state change transition. - internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) + internal ShutdownResult Shutdown(ReadOnlySpan data, bool force) { lock (_shutdownLock) { @@ -758,16 +759,16 @@ internal ShutdownResult Shutdown(byte[] data, int start, int length, bool force) Interlocked.Exchange(ref _timeSinceLastPacket, 0); //send shutdown packet - _shutdownPacket = new NetPacket(PacketProperty.Disconnect, length) {ConnectionNumber = _connectNum}; + _shutdownPacket = new NetPacket(PacketProperty.Disconnect, data.Length) {ConnectionNumber = _connectNum}; FastBitConverter.GetBytes(_shutdownPacket.RawData, 1, _connectTime); if (_shutdownPacket.Size >= _mtu) { //Drop additional data NetDebug.WriteError("[Peer] Disconnect additional data size more than MTU - 8!"); } - else if (data != null && length > 0) + else if (!data.IsEmpty) { - Buffer.BlockCopy(data, start, _shutdownPacket.RawData, 9, length); + data.CopyTo(_shutdownPacket.RawData.AsSpan(9)); } _connectionState = ConnectionState.ShutdownRequested; NetDebug.Write("[Peer] Send disconnect");