minecraft-src/net/minecraft/client/multiplayer/chat/report/ChatReportContextBuilder.java
2025-07-04 01:41:11 +03:00

111 lines
3.4 KiB
Java

package net.minecraft.client.multiplayer.chat.report;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntRBTreeSet;
import it.unimi.dsi.fastutil.ints.IntSortedSet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.multiplayer.chat.ChatLog;
import net.minecraft.client.multiplayer.chat.LoggedChatMessage;
import net.minecraft.network.chat.MessageSignature;
import net.minecraft.network.chat.PlayerChatMessage;
@Environment(EnvType.CLIENT)
public class ChatReportContextBuilder {
final int leadingCount;
private final List<ChatReportContextBuilder.Collector> activeCollectors = new ArrayList();
public ChatReportContextBuilder(int leadingCount) {
this.leadingCount = leadingCount;
}
public void collectAllContext(ChatLog chatLog, IntCollection reportedMessages, ChatReportContextBuilder.Handler handler) {
IntSortedSet intSortedSet = new IntRBTreeSet(reportedMessages);
for (int i = intSortedSet.lastInt(); i >= chatLog.start() && (this.isActive() || !intSortedSet.isEmpty()); i--) {
if (chatLog.lookup(i) instanceof LoggedChatMessage.Player player) {
boolean bl = this.acceptContext(player.message());
if (intSortedSet.remove(i)) {
this.trackContext(player.message());
handler.accept(i, player);
} else if (bl) {
handler.accept(i, player);
}
}
}
}
public void trackContext(PlayerChatMessage lastChainMessage) {
this.activeCollectors.add(new ChatReportContextBuilder.Collector(lastChainMessage));
}
public boolean acceptContext(PlayerChatMessage lastChainMessage) {
boolean bl = false;
Iterator<ChatReportContextBuilder.Collector> iterator = this.activeCollectors.iterator();
while (iterator.hasNext()) {
ChatReportContextBuilder.Collector collector = (ChatReportContextBuilder.Collector)iterator.next();
if (collector.accept(lastChainMessage)) {
bl = true;
if (collector.isComplete()) {
iterator.remove();
}
}
}
return bl;
}
public boolean isActive() {
return !this.activeCollectors.isEmpty();
}
@Environment(EnvType.CLIENT)
class Collector {
private final Set<MessageSignature> lastSeenSignatures;
private PlayerChatMessage lastChainMessage;
private boolean collectingChain = true;
private int count;
Collector(final PlayerChatMessage lastChainMessage) {
this.lastSeenSignatures = new ObjectOpenHashSet<>(lastChainMessage.signedBody().lastSeen().entries());
this.lastChainMessage = lastChainMessage;
}
boolean accept(PlayerChatMessage message) {
if (message.equals(this.lastChainMessage)) {
return false;
} else {
boolean bl = this.lastSeenSignatures.remove(message.signature());
if (this.collectingChain && this.lastChainMessage.sender().equals(message.sender())) {
if (this.lastChainMessage.link().isDescendantOf(message.link())) {
bl = true;
this.lastChainMessage = message;
} else {
this.collectingChain = false;
}
}
if (bl) {
this.count++;
}
return bl;
}
}
boolean isComplete() {
return this.count >= ChatReportContextBuilder.this.leadingCount || !this.collectingChain && this.lastSeenSignatures.isEmpty();
}
}
@Environment(EnvType.CLIENT)
public interface Handler {
void accept(int i, LoggedChatMessage.Player player);
}
}