public void SendPacketUnqueued(NetworkManager.OutgoingPacket outgoingPacket)
{
Packet packet = outgoingPacket.Packet;
byte[] buffer;
int bytes;
// Set sequence implies that this is not a resent packet
if (outgoingPacket.SetSequence)
{
// Reset to zero if we've hit the upper sequence number limit
Interlocked.CompareExchange(ref Sequence.seq, 0, Settings.MAX_SEQUENCE);
// Increment and fetch the current sequence number
packet.Header.Sequence = (uint)Interlocked.Increment(ref Sequence.seq);
if (packet.Header.Reliable)
{
// Keep track of when this packet was sent out (right now)
outgoingPacket.TickCount = Environment.TickCount;
// Add this packet to the list of ACK responses we are waiting on from the server
lock (NeedAck) NeedAck[packet.Header.Sequence] = outgoingPacket;
if (!packet.Header.Resent)
{
// This packet is not a resend, check if the conditions are favorable
// to ACK appending
if (packet.Type != PacketType.PacketAck &&
packet.Type != PacketType.LogoutRequest)
{
lock (PendingAcks)
{
if (PendingAcks.Count > 0 &&
PendingAcks.Count < Client.Settings.MAX_APPENDED_ACKS)
{
// Append all of the queued up outgoing ACKs to this packet
packet.Header.AckList = new uint[PendingAcks.Count];
for (int i = 0; i < PendingAcks.Count; i++)
packet.Header.AckList[i] = PendingAcks.Values[i];
PendingAcks.Clear();
packet.Header.AppendedAcks = true;
}
}
}
}
}
else if (packet.Header.AckList.Length > 0)
{
// Sanity check for ACKS appended on an unreliable packet, this is bad form
Logger.Log("Sending appended ACKs on an unreliable packet", Helpers.LogLevel.Warning);
}
}
if (packet.Header.Resent)
{
// This packet has already been sent out once, strip any appended ACKs
// off it and reinsert them into the outgoing ACK queue under the
// assumption that this packet will continually be rejected from the
// server or that the appended ACKs are possibly making the delivery fail
if (packet.Header.AckList.Length > 0)
{
Logger.DebugLog(String.Format("Purging ACKs from packet #{0} ({1}) which will be resent.",
packet.Header.Sequence, packet.GetType()));
lock (PendingAcks)
{
foreach (uint sequence in packet.Header.AckList)
{
if (!PendingAcks.ContainsKey(sequence))
PendingAcks[sequence] = sequence;
}
}
packet.Header.AppendedAcks = false;
packet.Header.AckList = new uint[0];
}
}
// Serialize the packet
buffer = packet.ToBytes();
bytes = buffer.Length;
Stats.SentBytes += (ulong)bytes;
++Stats.SentPackets;
UDPPacketBuffer buf = new UDPPacketBuffer(remoteEndPoint);
// Zerocode if needed
if (packet.Header.Zerocoded)
bytes = Helpers.ZeroEncode(buffer, bytes, buf.Data);
else
Buffer.BlockCopy(buffer, 0, buf.Data, 0, bytes);
buf.DataLength = bytes;
AsyncBeginSend(buf);
}