2022-08-27 02:10:44 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
2023-01-14 00:53:36 +08:00
|
|
|
|
using System.Linq;
|
2023-01-13 16:12:10 +08:00
|
|
|
|
using System.Security.Permissions;
|
|
|
|
|
|
using static MinecraftClient.Protocol.Message.LastSeenMessageList;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
|
|
|
|
|
namespace MinecraftClient.Protocol.Message
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A list of messages a client has seen.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class LastSeenMessageList
|
|
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public static readonly LastSeenMessageList EMPTY = new(Array.Empty<AcknowledgedMessage>());
|
2022-08-27 02:10:44 +08:00
|
|
|
|
public static readonly int MAX_ENTRIES = 5;
|
|
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public AcknowledgedMessage[] entries;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public LastSeenMessageList(AcknowledgedMessage[] list)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
entries = list;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void WriteForSign(List<byte> data)
|
|
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
foreach (AcknowledgedMessage entry in entries)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
data.Add(70);
|
|
|
|
|
|
data.AddRange(entry.profileId.ToBigEndianBytes());
|
2023-01-13 16:12:10 +08:00
|
|
|
|
data.AddRange(entry.signature);
|
2022-08-27 02:10:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A pair of a player's UUID and the signature of the last message they saw, used as an entry of LastSeenMessageList.
|
|
|
|
|
|
/// </summary>
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public record AcknowledgedMessage
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public bool pending;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
public Guid profileId;
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public byte[] signature;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public AcknowledgedMessage(Guid profileId, byte[] lastSignature, bool pending)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
this.profileId = profileId;
|
2023-01-13 16:12:10 +08:00
|
|
|
|
this.signature = lastSignature;
|
|
|
|
|
|
this.pending = pending;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public AcknowledgedMessage UnmarkAsPending()
|
|
|
|
|
|
{
|
|
|
|
|
|
return this.pending ? new AcknowledgedMessage(profileId, signature, false) : this;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// A record of messages acknowledged by a client.
|
|
|
|
|
|
/// This holds the messages the client has recently seen, as well as the last message they received, if any.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class Acknowledgment
|
|
|
|
|
|
{
|
|
|
|
|
|
public LastSeenMessageList lastSeen;
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public AcknowledgedMessage? lastReceived;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public Acknowledgment(LastSeenMessageList lastSeenMessageList, AcknowledgedMessage? lastReceivedMessage)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
|
|
|
|
|
lastSeen = lastSeenMessageList;
|
|
|
|
|
|
lastReceived = lastReceivedMessage;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Collects the message that are last seen by a client.
|
|
|
|
|
|
/// The message, along with the "last received" message, forms an "acknowledgment" of received messages.
|
|
|
|
|
|
/// They are sent to the server when the client has enough messages received or when they send a message.
|
|
|
|
|
|
/// The maximum amount of message entries are specified in the constructor.The vanilla clients collect 5 entries.
|
|
|
|
|
|
/// Calling add adds the message to the beginning of the entries list, and evicts the oldest message.
|
|
|
|
|
|
/// If there are entries with the same sender profile ID, the older entry will be replaced with null instead of filling the hole.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class LastSeenMessagesCollector
|
|
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
private readonly LastSeenMessageList.AcknowledgedMessage?[] acknowledgedMessages;
|
|
|
|
|
|
private int nextIndex = 0;
|
|
|
|
|
|
internal int messageCount { private set; get; } = 0;
|
|
|
|
|
|
private LastSeenMessageList.AcknowledgedMessage? lastEntry = null;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
private LastSeenMessageList lastSeenMessages;
|
|
|
|
|
|
|
|
|
|
|
|
public LastSeenMessagesCollector(int size)
|
|
|
|
|
|
{
|
|
|
|
|
|
lastSeenMessages = LastSeenMessageList.EMPTY;
|
2023-01-13 16:12:10 +08:00
|
|
|
|
acknowledgedMessages = new LastSeenMessageList.AcknowledgedMessage[size];
|
2022-08-27 02:10:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public void Add_1_19_2(LastSeenMessageList.AcknowledgedMessage entry)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
LastSeenMessageList.AcknowledgedMessage? lastEntry = entry;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
for (int i = 0; i < messageCount; ++i)
|
2022-08-27 02:10:44 +08:00
|
|
|
|
{
|
2023-01-13 16:12:10 +08:00
|
|
|
|
LastSeenMessageList.AcknowledgedMessage curEntry = acknowledgedMessages[i]!;
|
|
|
|
|
|
acknowledgedMessages[i] = lastEntry;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
lastEntry = curEntry;
|
|
|
|
|
|
if (curEntry.profileId == entry.profileId)
|
|
|
|
|
|
{
|
|
|
|
|
|
lastEntry = null;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
if (lastEntry != null && messageCount < acknowledgedMessages.Length)
|
|
|
|
|
|
acknowledgedMessages[messageCount++] = lastEntry;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
LastSeenMessageList.AcknowledgedMessage[] msgList = new LastSeenMessageList.AcknowledgedMessage[messageCount];
|
|
|
|
|
|
for (int i = 0; i < messageCount; ++i)
|
|
|
|
|
|
msgList[i] = acknowledgedMessages[i]!;
|
2022-08-27 02:10:44 +08:00
|
|
|
|
lastSeenMessages = new LastSeenMessageList(msgList);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public bool Add_1_19_3(LastSeenMessageList.AcknowledgedMessage entry, bool displayed)
|
|
|
|
|
|
{
|
|
|
|
|
|
// net.minecraft.network.message.LastSeenMessagesCollector#add(net.minecraft.network.message.MessageSignatureData, boolean)
|
|
|
|
|
|
// net.minecraft.network.message.LastSeenMessagesCollector#add(net.minecraft.network.message.AcknowledgedMessage)
|
2023-01-14 00:53:36 +08:00
|
|
|
|
if (lastEntry != null && entry.signature.SequenceEqual(lastEntry.signature))
|
2023-01-13 16:12:10 +08:00
|
|
|
|
return false;
|
|
|
|
|
|
lastEntry = entry;
|
|
|
|
|
|
|
|
|
|
|
|
int index = nextIndex;
|
|
|
|
|
|
nextIndex = (index + 1) % acknowledgedMessages.Length;
|
|
|
|
|
|
|
|
|
|
|
|
++messageCount;
|
|
|
|
|
|
acknowledgedMessages[index] = displayed ? entry : null;
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public Tuple<AcknowledgedMessage[], byte[], int> Collect_1_19_3()
|
|
|
|
|
|
{
|
|
|
|
|
|
// net.minecraft.network.message.LastSeenMessagesCollector#collect
|
|
|
|
|
|
int count = ResetMessageCount();
|
|
|
|
|
|
byte[] bitset = new byte[3]; // new Bitset(20); Todo: Use a complete bitset implementation.
|
|
|
|
|
|
List<AcknowledgedMessage> objectList = new(acknowledgedMessages.Length);
|
|
|
|
|
|
for (int j = 0; j < acknowledgedMessages.Length; ++j)
|
|
|
|
|
|
{
|
|
|
|
|
|
int k = (nextIndex + j) % acknowledgedMessages.Length;
|
|
|
|
|
|
AcknowledgedMessage? acknowledgedMessage = acknowledgedMessages[k];
|
|
|
|
|
|
if (acknowledgedMessage == null)
|
|
|
|
|
|
continue;
|
|
|
|
|
|
bitset[j / 8] |= (byte)(1 << (j % 8)); // bitSet.set(j, true);
|
|
|
|
|
|
objectList.Add(acknowledgedMessage);
|
|
|
|
|
|
acknowledgedMessages[k] = acknowledgedMessage.UnmarkAsPending();
|
|
|
|
|
|
}
|
|
|
|
|
|
return new(objectList.ToArray(), bitset, count);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-08-27 02:10:44 +08:00
|
|
|
|
public LastSeenMessageList GetLastSeenMessages()
|
|
|
|
|
|
{
|
|
|
|
|
|
return lastSeenMessages;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-01-13 16:12:10 +08:00
|
|
|
|
public int ResetMessageCount()
|
|
|
|
|
|
{
|
|
|
|
|
|
// net.minecraft.network.message.LastSeenMessagesCollector#resetMessageCount
|
|
|
|
|
|
int cnt = messageCount;
|
|
|
|
|
|
messageCount = 0;
|
|
|
|
|
|
return cnt;
|
|
|
|
|
|
}
|
2022-08-27 02:10:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|