Progress on tutorial, gap tweaking (water flows faster from room to room), UPnP error messages, input keys in array, underwater aiming tweaking, tons of misc stuff commit more often ffs
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Lidgren.Network
|
||||
{
|
||||
internal class ReceivedFragmentGroup
|
||||
{
|
||||
public float LastReceived;
|
||||
public byte[] Data;
|
||||
public NetBitVector ReceivedChunks;
|
||||
}
|
||||
|
||||
public partial class NetPeer
|
||||
{
|
||||
private int m_lastUsedFragmentGroup;
|
||||
|
||||
private Dictionary<NetConnection, Dictionary<int, ReceivedFragmentGroup>> m_receivedFragmentGroups;
|
||||
|
||||
// on user thread
|
||||
private void SendFragmentedMessage(NetOutgoingMessage msg, IList<NetConnection> recipients, NetDeliveryMethod method, int sequenceChannel)
|
||||
{
|
||||
// Note: this group id is PER SENDING/NetPeer; ie. same id is sent to all recipients;
|
||||
// this should be ok however; as long as recipients differentiate between same id but different sender
|
||||
int group = Interlocked.Increment(ref m_lastUsedFragmentGroup);
|
||||
if (group >= NetConstants.MaxFragmentationGroups)
|
||||
{
|
||||
// @TODO: not thread safe; but in practice probably not an issue
|
||||
m_lastUsedFragmentGroup = 1;
|
||||
group = 1;
|
||||
}
|
||||
msg.m_fragmentGroup = group;
|
||||
|
||||
// do not send msg; but set fragmentgroup in case user tries to recycle it immediately
|
||||
|
||||
// create fragmentation specifics
|
||||
int totalBytes = msg.LengthBytes;
|
||||
|
||||
// determine minimum mtu for all recipients
|
||||
int mtu = GetMTU(recipients);
|
||||
int bytesPerChunk = NetFragmentationHelper.GetBestChunkSize(group, totalBytes, mtu);
|
||||
|
||||
int numChunks = totalBytes / bytesPerChunk;
|
||||
if (numChunks * bytesPerChunk < totalBytes)
|
||||
numChunks++;
|
||||
|
||||
int bitsPerChunk = bytesPerChunk * 8;
|
||||
int bitsLeft = msg.LengthBits;
|
||||
for (int i = 0; i < numChunks; i++)
|
||||
{
|
||||
NetOutgoingMessage chunk = CreateMessage(mtu);
|
||||
|
||||
chunk.m_bitLength = (bitsLeft > bitsPerChunk ? bitsPerChunk : bitsLeft);
|
||||
chunk.m_data = msg.m_data;
|
||||
chunk.m_fragmentGroup = group;
|
||||
chunk.m_fragmentGroupTotalBits = totalBytes * 8;
|
||||
chunk.m_fragmentChunkByteSize = bytesPerChunk;
|
||||
chunk.m_fragmentChunkNumber = i;
|
||||
|
||||
NetException.Assert(chunk.m_bitLength != 0);
|
||||
NetException.Assert(chunk.GetEncodedSize() < mtu);
|
||||
|
||||
Interlocked.Add(ref chunk.m_recyclingCount, recipients.Count);
|
||||
|
||||
foreach (NetConnection recipient in recipients)
|
||||
recipient.EnqueueMessage(chunk, method, sequenceChannel);
|
||||
|
||||
bitsLeft -= bitsPerChunk;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private void HandleReleasedFragment(NetIncomingMessage im)
|
||||
{
|
||||
VerifyNetworkThread();
|
||||
|
||||
//
|
||||
// read fragmentation header and combine fragments
|
||||
//
|
||||
int group;
|
||||
int totalBits;
|
||||
int chunkByteSize;
|
||||
int chunkNumber;
|
||||
int ptr = NetFragmentationHelper.ReadHeader(
|
||||
im.m_data, 0,
|
||||
out group,
|
||||
out totalBits,
|
||||
out chunkByteSize,
|
||||
out chunkNumber
|
||||
);
|
||||
|
||||
NetException.Assert(im.LengthBytes > ptr);
|
||||
|
||||
NetException.Assert(group > 0);
|
||||
NetException.Assert(totalBits > 0);
|
||||
NetException.Assert(chunkByteSize > 0);
|
||||
|
||||
int totalBytes = NetUtility.BytesToHoldBits((int)totalBits);
|
||||
int totalNumChunks = totalBytes / chunkByteSize;
|
||||
if (totalNumChunks * chunkByteSize < totalBytes)
|
||||
totalNumChunks++;
|
||||
|
||||
NetException.Assert(chunkNumber < totalNumChunks);
|
||||
|
||||
if (chunkNumber >= totalNumChunks)
|
||||
{
|
||||
LogWarning("Index out of bounds for chunk " + chunkNumber + " (total chunks " + totalNumChunks + ")");
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary<int, ReceivedFragmentGroup> groups;
|
||||
if (!m_receivedFragmentGroups.TryGetValue(im.SenderConnection, out groups))
|
||||
{
|
||||
groups = new Dictionary<int, ReceivedFragmentGroup>();
|
||||
m_receivedFragmentGroups[im.SenderConnection] = groups;
|
||||
}
|
||||
|
||||
ReceivedFragmentGroup info;
|
||||
if (!groups.TryGetValue(group, out info))
|
||||
{
|
||||
info = new ReceivedFragmentGroup();
|
||||
info.Data = new byte[totalBytes];
|
||||
info.ReceivedChunks = new NetBitVector(totalNumChunks);
|
||||
groups[group] = info;
|
||||
}
|
||||
|
||||
info.ReceivedChunks[chunkNumber] = true;
|
||||
info.LastReceived = (float)NetTime.Now;
|
||||
|
||||
// copy to data
|
||||
int offset = (chunkNumber * chunkByteSize);
|
||||
Buffer.BlockCopy(im.m_data, ptr, info.Data, offset, im.LengthBytes - ptr);
|
||||
|
||||
int cnt = info.ReceivedChunks.Count();
|
||||
//LogVerbose("Found fragment #" + chunkNumber + " in group " + group + " offset " + offset + " of total bits " + totalBits + " (total chunks done " + cnt + ")");
|
||||
|
||||
LogVerbose("Received fragment " + chunkNumber + " of " + totalNumChunks + " (" + cnt + " chunks received)");
|
||||
|
||||
if (info.ReceivedChunks.Count() == totalNumChunks)
|
||||
{
|
||||
// Done! Transform this incoming message
|
||||
im.m_data = info.Data;
|
||||
im.m_bitLength = (int)totalBits;
|
||||
im.m_isFragment = false;
|
||||
|
||||
LogVerbose("Fragment group #" + group + " fully received in " + totalNumChunks + " chunks (" + totalBits + " bits)");
|
||||
groups.Remove(group);
|
||||
|
||||
ReleaseMessage(im);
|
||||
}
|
||||
else
|
||||
{
|
||||
// data has been copied; recycle this incoming message
|
||||
Recycle(im);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user