v1.3.0.1 (Epic Store release)
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class MessageDefragmenter
|
||||
{
|
||||
private readonly Dictionary<ushort, MessageFragment[]> partialMessages = new Dictionary<ushort, MessageFragment[]>();
|
||||
|
||||
public Option<ImmutableArray<byte>> ProcessIncomingFragment(MessageFragment fragment)
|
||||
{
|
||||
if (!partialMessages.ContainsKey(fragment.FragmentId.MessageId))
|
||||
{
|
||||
partialMessages[fragment.FragmentId.MessageId] = new MessageFragment[fragment.FragmentId.FragmentCount];
|
||||
}
|
||||
else if (partialMessages[fragment.FragmentId.MessageId].Length != fragment.FragmentId.FragmentCount)
|
||||
{
|
||||
DebugConsole.AddWarning($"Got a fragment for message {fragment.FragmentId.MessageId} " +
|
||||
$"with a mismatched expected fragment count");
|
||||
return Option.None;
|
||||
}
|
||||
|
||||
var fragmentBuffer = partialMessages[fragment.FragmentId.MessageId];
|
||||
if (fragment.FragmentId.FragmentIndex >= fragmentBuffer.Length)
|
||||
{
|
||||
DebugConsole.AddWarning($"Got a fragment for message {fragment.FragmentId.MessageId} " +
|
||||
$"with an index greater than or equal to the expected fragment count ({fragment.FragmentId.FragmentIndex} >= {fragmentBuffer.Length})");
|
||||
return Option.None;
|
||||
}
|
||||
|
||||
fragmentBuffer[fragment.FragmentId.FragmentIndex] = fragment;
|
||||
if (fragmentBuffer.All(f => !f.Data.IsDefault && f.FragmentId.MessageId == fragment.FragmentId.MessageId))
|
||||
{
|
||||
partialMessages.Remove(fragment.FragmentId.MessageId);
|
||||
return Option.Some(fragmentBuffer.SelectMany(f => f.Data).ToImmutableArray());
|
||||
}
|
||||
return Option.None;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
[NetworkSerialize(ArrayMaxSize = MaxSize)]
|
||||
readonly record struct MessageFragment(
|
||||
MessageFragment.Id FragmentId,
|
||||
ImmutableArray<byte> Data) : INetSerializableStruct
|
||||
{
|
||||
public const int MaxSize = 1100;
|
||||
|
||||
[NetworkSerialize]
|
||||
public readonly record struct Id(
|
||||
ushort FragmentIndex,
|
||||
ushort FragmentCount,
|
||||
ushort MessageId) : INetSerializableStruct;
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Barotrauma.Networking;
|
||||
|
||||
sealed class MessageFragmenter
|
||||
{
|
||||
private UInt16 nextFragmentedMessageId = 0;
|
||||
private readonly List<MessageFragment> fragments = new List<MessageFragment>();
|
||||
|
||||
public ImmutableArray<MessageFragment> FragmentMessage(ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
UInt16 msgId = nextFragmentedMessageId;
|
||||
nextFragmentedMessageId++;
|
||||
|
||||
int roundedByteCount = bytes.Length;
|
||||
roundedByteCount += (MessageFragment.MaxSize - (roundedByteCount % MessageFragment.MaxSize)) % MessageFragment.MaxSize;
|
||||
|
||||
int fragmentCount = roundedByteCount / MessageFragment.MaxSize;
|
||||
fragments.Clear();
|
||||
fragments.EnsureCapacity(fragmentCount);
|
||||
for (int i = 0; i < fragmentCount; i++)
|
||||
{
|
||||
var subset = bytes[(i * MessageFragment.MaxSize)..];
|
||||
if (subset.Length > MessageFragment.MaxSize) { subset = subset[..MessageFragment.MaxSize]; }
|
||||
|
||||
fragments.Add(new MessageFragment(
|
||||
FragmentId: new MessageFragment.Id(
|
||||
FragmentIndex: (ushort)i,
|
||||
FragmentCount: (ushort)fragmentCount,
|
||||
MessageId: msgId),
|
||||
Data: subset.ToArray().ToImmutableArray()));
|
||||
}
|
||||
|
||||
return fragments.ToImmutableArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user