minecraft-src/net/minecraft/client/gui/screens/reporting/ChatSelectionScreen.java
2025-07-04 03:45:38 +03:00

218 lines
9.4 KiB
Java

package net.minecraft.client.gui.screens.reporting;
import com.mojang.authlib.minecraft.report.AbuseReportLimits;
import java.util.function.Consumer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.GuiMessageTag;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.MultiLineLabel;
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.navigation.ScreenDirection;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.reporting.ChatSelectionLogFiller.Output;
import net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.DividerEntry;
import net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Heading;
import net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.MessageEntry;
import net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.MessageHeadingEntry;
import net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.PaddingEntry;
import net.minecraft.client.multiplayer.chat.ChatTrustLevel;
import net.minecraft.client.multiplayer.chat.LoggedChatMessage;
import net.minecraft.client.multiplayer.chat.LoggedChatMessage.Player;
import net.minecraft.client.multiplayer.chat.report.ReportingContext;
import net.minecraft.client.multiplayer.chat.report.ChatReport.Builder;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class ChatSelectionScreen extends Screen {
static final ResourceLocation CHECKMARK_SPRITE = ResourceLocation.withDefaultNamespace("icon/checkmark");
private static final Component TITLE = Component.translatable("gui.chatSelection.title");
private static final Component CONTEXT_INFO = Component.translatable("gui.chatSelection.context");
@Nullable
private final Screen lastScreen;
private final ReportingContext reportingContext;
private Button confirmSelectedButton;
private MultiLineLabel contextInfoLabel;
@Nullable
private ChatSelectionScreen.ChatSelectionList chatSelectionList;
final Builder report;
private final Consumer<Builder> onSelected;
private ChatSelectionLogFiller chatLogFiller;
public ChatSelectionScreen(@Nullable Screen lastScreen, ReportingContext reportingContext, Builder report, Consumer<Builder> onSelected) {
super(TITLE);
this.lastScreen = lastScreen;
this.reportingContext = reportingContext;
this.report = report.copy();
this.onSelected = onSelected;
}
@Override
protected void init() {
this.chatLogFiller = new ChatSelectionLogFiller(this.reportingContext, this::canReport);
this.contextInfoLabel = MultiLineLabel.create(this.font, CONTEXT_INFO, this.width - 16);
this.chatSelectionList = this.addRenderableWidget(new ChatSelectionScreen.ChatSelectionList(this.minecraft, (this.contextInfoLabel.getLineCount() + 1) * 9));
this.addRenderableWidget(Button.builder(CommonComponents.GUI_BACK, button -> this.onClose()).bounds(this.width / 2 - 155, this.height - 32, 150, 20).build());
this.confirmSelectedButton = this.addRenderableWidget(Button.builder(CommonComponents.GUI_DONE, button -> {
this.onSelected.accept(this.report);
this.onClose();
}).bounds(this.width / 2 - 155 + 160, this.height - 32, 150, 20).build());
this.updateConfirmSelectedButton();
this.extendLog();
this.chatSelectionList.setScrollAmount(this.chatSelectionList.maxScrollAmount());
}
private boolean canReport(LoggedChatMessage message) {
return message.canReport(this.report.reportedProfileId());
}
private void extendLog() {
int i = this.chatSelectionList.getMaxVisibleEntries();
this.chatLogFiller.fillNextPage(i, this.chatSelectionList);
}
void onReachedScrollTop() {
this.extendLog();
}
void updateConfirmSelectedButton() {
this.confirmSelectedButton.active = !this.report.reportedMessages().isEmpty();
}
@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
super.render(guiGraphics, mouseX, mouseY, partialTick);
guiGraphics.drawCenteredString(this.font, this.title, this.width / 2, 10, -1);
AbuseReportLimits abuseReportLimits = this.reportingContext.sender().reportLimits();
int i = this.report.reportedMessages().size();
int j = abuseReportLimits.maxReportedMessageCount();
Component component = Component.translatable("gui.chatSelection.selected", i, j);
guiGraphics.drawCenteredString(this.font, component, this.width / 2, 26, -1);
this.contextInfoLabel.renderCentered(guiGraphics, this.width / 2, this.chatSelectionList.getFooterTop());
}
@Override
public void onClose() {
this.minecraft.setScreen(this.lastScreen);
}
@Override
public Component getNarrationMessage() {
return CommonComponents.joinForNarration(super.getNarrationMessage(), CONTEXT_INFO);
}
@Environment(EnvType.CLIENT)
public class ChatSelectionList
extends ObjectSelectionList<net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry>
implements Output {
@Nullable
private Heading previousHeading;
public ChatSelectionList(final Minecraft minecraft, final int height) {
super(minecraft, ChatSelectionScreen.this.width, ChatSelectionScreen.this.height - height - 80, 40, 16);
}
@Override
public void setScrollAmount(double scrollAmount) {
double d = this.scrollAmount();
super.setScrollAmount(scrollAmount);
if (this.maxScrollAmount() > 1.0E-5F && scrollAmount <= 1.0E-5F && !Mth.equal(scrollAmount, d)) {
ChatSelectionScreen.this.onReachedScrollTop();
}
}
@Override
public void acceptMessage(int chatId, Player playerMessage) {
boolean bl = playerMessage.canReport(ChatSelectionScreen.this.report.reportedProfileId());
ChatTrustLevel chatTrustLevel = playerMessage.trustLevel();
GuiMessageTag guiMessageTag = chatTrustLevel.createTag(playerMessage.message());
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry = new MessageEntry(
this, chatId, playerMessage.toContentComponent(), playerMessage.toNarrationComponent(), guiMessageTag, bl, true
);
this.addEntryToTop(entry);
this.updateHeading(playerMessage, bl);
}
private void updateHeading(Player loggedPlayerChatMessage, boolean canReport) {
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry = new MessageHeadingEntry(
this, loggedPlayerChatMessage.profile(), loggedPlayerChatMessage.toHeadingComponent(), canReport
);
this.addEntryToTop(entry);
Heading heading = new Heading(loggedPlayerChatMessage.profileId(), entry);
if (this.previousHeading != null && this.previousHeading.canCombine(heading)) {
this.removeEntryFromTop(this.previousHeading.entry());
}
this.previousHeading = heading;
}
@Override
public void acceptDivider(Component text) {
this.addEntryToTop(new PaddingEntry());
this.addEntryToTop(new DividerEntry(this, text));
this.addEntryToTop(new PaddingEntry());
this.previousHeading = null;
}
@Override
public int getRowWidth() {
return Math.min(350, this.width - 50);
}
public int getMaxVisibleEntries() {
return Mth.positiveCeilDiv(this.height, this.itemHeight);
}
@Override
protected void renderItem(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick, int index, int left, int top, int width, int height) {
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry = this.getEntry(index);
if (this.shouldHighlightEntry(entry)) {
boolean bl = this.getSelected() == entry;
int i = this.isFocused() && bl ? -1 : -8355712;
this.renderSelection(guiGraphics, top, width, height, i, -16777216);
}
entry.render(guiGraphics, index, top, left, width, height, mouseX, mouseY, this.getHovered() == entry, partialTick);
}
private boolean shouldHighlightEntry(net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry) {
if (entry.canSelect()) {
boolean bl = this.getSelected() == entry;
boolean bl2 = this.getSelected() == null;
boolean bl3 = this.getHovered() == entry;
return bl || bl2 && bl3 && entry.canReport();
} else {
return false;
}
}
@Nullable
protected net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry nextEntry(ScreenDirection screenDirection) {
return this.nextEntry(screenDirection, net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry::canSelect);
}
public void setSelected(@Nullable net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry) {
super.setSelected(entry);
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry2 = this.nextEntry(ScreenDirection.UP);
if (entry2 == null) {
ChatSelectionScreen.this.onReachedScrollTop();
}
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
net.minecraft.client.gui.screens.reporting.ChatSelectionScreen.ChatSelectionList.Entry entry = this.getSelected();
return entry != null && entry.keyPressed(keyCode, scanCode, modifiers) ? true : super.keyPressed(keyCode, scanCode, modifiers);
}
public int getFooterTop() {
return this.getBottom() + 9;
}
}
}