namespace Supercell.Laser.Server.Networking { using Supercell.Laser.Logic.Avatar; using Supercell.Laser.Logic.Battle; using Supercell.Laser.Logic.Home; using Supercell.Laser.Logic.Message; using Supercell.Laser.Server.Logic.Game; using Supercell.Laser.Server.Message; using System; using System.Buffers; using System.Net.Sockets; public class Connection { public const int ReadBufferSize = 4096; // Монотонно-растущий счётчик: уникальный int-ключ для ConcurrentDictionary в TCPGateway. // Используем Interlocked чтобы не нужен был отдельный лок при параллельном accept. private static int _idCounter; public int Id { get; } = Interlocked.Increment(ref _idCounter); public Messaging Messaging { get; } public MessageManager MessageManager { get; } public byte[] ReadBuffer { get; private set; } public Socket Socket { get; } public int Ping { get; private set; } public MemoryStream Memory { get; set; } public bool IsOpen; public int MatchmakeSlot; public MatchmakingEntry MatchmakingEntry; public long UdpSessionId; public DateTime LastActiveTime { get; private set; } public ClientHome Home { get { if (MessageManager.HomeMode != null) { return MessageManager.HomeMode.Home; } return null; } } public ClientAvatar Avatar { get { if (MessageManager.HomeMode != null) { return MessageManager.HomeMode.Avatar; } return null; } } public Connection(Socket socket) { Socket = socket; ReadBuffer = ArrayPool.Shared.Rent(ReadBufferSize); Memory = new MemoryStream(ReadBufferSize); Messaging = new Messaging(this); MessageManager = new MessageManager(this); IsOpen = true; MatchmakeSlot = -1; UdpSessionId = -1; } public void PingUpdated(int value) { Ping = value; } public void Send(GameMessage message) { Messaging.Send(message); } public void Close() { try { IsOpen = false; Socket.Close(); } catch (Exception) { } try { Memory?.Dispose(); Memory = null; } catch (Exception) { } if (ReadBuffer != null) { ArrayPool.Shared.Return(ReadBuffer); ReadBuffer = null; } } public void Write(byte[] stream) { try { WireDump.Write($"TCP-SEND account={Avatar?.AccountId ?? 0}", stream, 0, stream.Length); Socket.BeginSend(stream, 0, stream.Length, SocketFlags.None, new AsyncCallback(TCPGateway.OnSend), Socket); } catch (Exception) { } } public void UpdateLastActiveTime() { LastActiveTime = DateTime.Now; } } }