/// <summary>
            ///     Returns this object back to the object pool from whence it came.
            /// </summary>
            public void Recycle()
            {
                this.Acknowledged = true;
                this.Connection   = null;

                PacketPool.PutObject(this);
            }
            // Packets resent
            public async ValueTask <int> Resend()
            {
                UdpConnection connection = this.Connection;

                if (!this.Acknowledged && connection != null)
                {
                    long lifetime = this.Stopwatch.ElapsedMilliseconds;
                    if (lifetime >= connection.DisconnectTimeout)
                    {
                        if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self))
                        {
                            await connection.DisconnectInternal(HazelInternalErrors.ReliablePacketWithoutResponse, $"Reliable packet {self.Id} (size={this.Length}) was not ack'd after {lifetime}ms ({self.Retransmissions} resends)");

                            self.Recycle();
                        }

                        return(0);
                    }

                    if (lifetime >= this.NextTimeout)
                    {
                        ++this.Retransmissions;
                        if (connection.ResendLimit != 0 &&
                            this.Retransmissions > connection.ResendLimit)
                        {
                            if (connection.reliableDataPacketsSent.TryRemove(this.Id, out Packet self))
                            {
                                await connection.DisconnectInternal(HazelInternalErrors.ReliablePacketWithoutResponse, $"Reliable packet {self.Id} (size={this.Length}) was not ack'd after {self.Retransmissions} resends ({lifetime}ms)");

                                self.Recycle();
                            }

                            return(0);
                        }

                        this.NextTimeout += (int)Math.Min(this.NextTimeout * connection.ResendPingMultiplier, 1000);
                        try
                        {
                            await connection.WriteBytesToConnection(this.Data, this.Length);

                            connection.Statistics.LogMessageResent();
                            return(1);
                        }
                        catch (InvalidOperationException)
                        {
                            await connection.DisconnectInternal(HazelInternalErrors.ConnectionDisconnected, "Could not resend data as connection is no longer connected");
                        }
                    }
                }

                return(0);
            }
            internal void Set(ushort id, UdpConnection connection, byte[] data, int length, int timeout, Action ackCallback)
            {
                this.Id         = id;
                this.Data       = data;
                this.Connection = connection;
                this.Length     = length;

                this.Acknowledged    = false;
                this.NextTimeout     = timeout;
                this.AckCallback     = ackCallback;
                this.Retransmissions = 0;

                this.Stopwatch.Restart();
            }