343 lines
18 KiB
Java
343 lines
18 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.collect.Lists
|
|
* com.mojang.datafixers.util.Either
|
|
* com.mojang.logging.LogUtils
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package com.mojang.realmsclient.gui.screens;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.datafixers.util.Either;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.realmsclient.client.RealmsClient;
|
|
import com.mojang.realmsclient.dto.RealmsServer;
|
|
import com.mojang.realmsclient.dto.WorldTemplate;
|
|
import com.mojang.realmsclient.dto.WorldTemplatePaginatedList;
|
|
import com.mojang.realmsclient.exception.RealmsServiceException;
|
|
import com.mojang.realmsclient.util.RealmsTextureManager;
|
|
import com.mojang.realmsclient.util.TextRenderingUtils;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.function.Consumer;
|
|
import java.util.stream.Collectors;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.GuiGraphics;
|
|
import net.minecraft.client.gui.components.AbstractWidget;
|
|
import net.minecraft.client.gui.components.Button;
|
|
import net.minecraft.client.gui.components.ImageButton;
|
|
import net.minecraft.client.gui.components.ObjectSelectionList;
|
|
import net.minecraft.client.gui.components.StringWidget;
|
|
import net.minecraft.client.gui.components.Tooltip;
|
|
import net.minecraft.client.gui.components.WidgetSprites;
|
|
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
|
|
import net.minecraft.client.gui.layouts.LinearLayout;
|
|
import net.minecraft.client.gui.screens.ConfirmLinkScreen;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.client.input.MouseButtonEvent;
|
|
import net.minecraft.client.renderer.RenderPipelines;
|
|
import net.minecraft.client.resources.language.I18n;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.realms.RealmsScreen;
|
|
import net.minecraft.resources.Identifier;
|
|
import net.minecraft.util.CommonLinks;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class RealmsSelectWorldTemplateScreen
|
|
extends RealmsScreen {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final Identifier SLOT_FRAME_SPRITE = Identifier.withDefaultNamespace("widget/slot_frame");
|
|
private static final Component SELECT_BUTTON_NAME = Component.translatable("mco.template.button.select");
|
|
private static final Component TRAILER_BUTTON_NAME = Component.translatable("mco.template.button.trailer");
|
|
private static final Component PUBLISHER_BUTTON_NAME = Component.translatable("mco.template.button.publisher");
|
|
private static final int BUTTON_WIDTH = 100;
|
|
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this);
|
|
private final Consumer<WorldTemplate> callback;
|
|
private WorldTemplateList worldTemplateList;
|
|
private final RealmsServer.WorldType worldType;
|
|
private final List<Component> subtitle;
|
|
private Button selectButton;
|
|
private Button trailerButton;
|
|
private Button publisherButton;
|
|
private @Nullable WorldTemplate selectedTemplate = null;
|
|
private @Nullable String currentLink;
|
|
private @Nullable List<TextRenderingUtils.Line> noTemplatesMessage;
|
|
|
|
public RealmsSelectWorldTemplateScreen(Component title, Consumer<WorldTemplate> callback, RealmsServer.WorldType worldType, @Nullable WorldTemplatePaginatedList alreadyFetched) {
|
|
this(title, callback, worldType, alreadyFetched, List.of());
|
|
}
|
|
|
|
public RealmsSelectWorldTemplateScreen(Component title, Consumer<WorldTemplate> callback, RealmsServer.WorldType worldType, @Nullable WorldTemplatePaginatedList alreadyFetched, List<Component> subtitle) {
|
|
super(title);
|
|
this.callback = callback;
|
|
this.worldType = worldType;
|
|
if (alreadyFetched == null) {
|
|
this.worldTemplateList = new WorldTemplateList();
|
|
this.fetchTemplatesAsync(new WorldTemplatePaginatedList(10));
|
|
} else {
|
|
this.worldTemplateList = new WorldTemplateList(Lists.newArrayList(alreadyFetched.templates()));
|
|
this.fetchTemplatesAsync(alreadyFetched);
|
|
}
|
|
this.subtitle = subtitle;
|
|
}
|
|
|
|
@Override
|
|
public void init() {
|
|
this.layout.setHeaderHeight(33 + this.subtitle.size() * (this.getFont().lineHeight + 4));
|
|
LinearLayout header = this.layout.addToHeader(LinearLayout.vertical().spacing(4));
|
|
header.defaultCellSetting().alignHorizontallyCenter();
|
|
header.addChild(new StringWidget(this.title, this.font));
|
|
this.subtitle.forEach(warning -> header.addChild(new StringWidget((Component)warning, this.font)));
|
|
this.worldTemplateList = this.layout.addToContents(new WorldTemplateList(this.worldTemplateList.getTemplates()));
|
|
LinearLayout bottomButtons = this.layout.addToFooter(LinearLayout.horizontal().spacing(8));
|
|
bottomButtons.defaultCellSetting().alignHorizontallyCenter();
|
|
this.trailerButton = bottomButtons.addChild(Button.builder(TRAILER_BUTTON_NAME, button -> this.onTrailer()).width(100).build());
|
|
this.selectButton = bottomButtons.addChild(Button.builder(SELECT_BUTTON_NAME, button -> this.selectTemplate()).width(100).build());
|
|
bottomButtons.addChild(Button.builder(CommonComponents.GUI_CANCEL, button -> this.onClose()).width(100).build());
|
|
this.publisherButton = bottomButtons.addChild(Button.builder(PUBLISHER_BUTTON_NAME, button -> this.onPublish()).width(100).build());
|
|
this.updateButtonStates();
|
|
this.layout.visitWidgets(x$0 -> {
|
|
AbstractWidget cfr_ignored_0 = (AbstractWidget)this.addRenderableWidget(x$0);
|
|
});
|
|
this.repositionElements();
|
|
}
|
|
|
|
@Override
|
|
protected void repositionElements() {
|
|
this.worldTemplateList.updateSize(this.width, this.layout);
|
|
this.layout.arrangeElements();
|
|
}
|
|
|
|
@Override
|
|
public Component getNarrationMessage() {
|
|
ArrayList parts = Lists.newArrayListWithCapacity((int)2);
|
|
parts.add(this.title);
|
|
parts.addAll(this.subtitle);
|
|
return CommonComponents.joinLines(parts);
|
|
}
|
|
|
|
private void updateButtonStates() {
|
|
this.publisherButton.visible = this.selectedTemplate != null && !this.selectedTemplate.link().isEmpty();
|
|
this.trailerButton.visible = this.selectedTemplate != null && !this.selectedTemplate.trailer().isEmpty();
|
|
this.selectButton.active = this.selectedTemplate != null;
|
|
}
|
|
|
|
@Override
|
|
public void onClose() {
|
|
this.callback.accept(null);
|
|
}
|
|
|
|
private void selectTemplate() {
|
|
if (this.selectedTemplate != null) {
|
|
this.callback.accept(this.selectedTemplate);
|
|
}
|
|
}
|
|
|
|
private void onTrailer() {
|
|
if (this.selectedTemplate != null && !this.selectedTemplate.trailer().isBlank()) {
|
|
ConfirmLinkScreen.confirmLinkNow((Screen)this, this.selectedTemplate.trailer());
|
|
}
|
|
}
|
|
|
|
private void onPublish() {
|
|
if (this.selectedTemplate != null && !this.selectedTemplate.link().isBlank()) {
|
|
ConfirmLinkScreen.confirmLinkNow((Screen)this, this.selectedTemplate.link());
|
|
}
|
|
}
|
|
|
|
private void fetchTemplatesAsync(final WorldTemplatePaginatedList startPage) {
|
|
new Thread("realms-template-fetcher"){
|
|
|
|
@Override
|
|
public void run() {
|
|
WorldTemplatePaginatedList page = startPage;
|
|
RealmsClient client = RealmsClient.getOrCreate();
|
|
while (page != null) {
|
|
Either<WorldTemplatePaginatedList, Exception> result = RealmsSelectWorldTemplateScreen.this.fetchTemplates(page, client);
|
|
page = RealmsSelectWorldTemplateScreen.this.minecraft.submit(() -> {
|
|
if (result.right().isPresent()) {
|
|
LOGGER.error("Couldn't fetch templates", (Throwable)result.right().get());
|
|
if (RealmsSelectWorldTemplateScreen.this.worldTemplateList.isEmpty()) {
|
|
RealmsSelectWorldTemplateScreen.this.noTemplatesMessage = TextRenderingUtils.decompose(I18n.get("mco.template.select.failure", new Object[0]), new TextRenderingUtils.LineSegment[0]);
|
|
}
|
|
return null;
|
|
}
|
|
WorldTemplatePaginatedList currentPage = (WorldTemplatePaginatedList)result.left().get();
|
|
for (WorldTemplate template : currentPage.templates()) {
|
|
RealmsSelectWorldTemplateScreen.this.worldTemplateList.addEntry(template);
|
|
}
|
|
if (currentPage.templates().isEmpty()) {
|
|
if (RealmsSelectWorldTemplateScreen.this.worldTemplateList.isEmpty()) {
|
|
String withoutLink = I18n.get("mco.template.select.none", "%link");
|
|
TextRenderingUtils.LineSegment link = TextRenderingUtils.LineSegment.link(I18n.get("mco.template.select.none.linkTitle", new Object[0]), CommonLinks.REALMS_CONTENT_CREATION.toString());
|
|
RealmsSelectWorldTemplateScreen.this.noTemplatesMessage = TextRenderingUtils.decompose(withoutLink, link);
|
|
}
|
|
return null;
|
|
}
|
|
return currentPage;
|
|
}).join();
|
|
}
|
|
}
|
|
}.start();
|
|
}
|
|
|
|
private Either<WorldTemplatePaginatedList, Exception> fetchTemplates(WorldTemplatePaginatedList paginatedList, RealmsClient client) {
|
|
try {
|
|
return Either.left((Object)client.fetchWorldTemplates(paginatedList.page() + 1, paginatedList.size(), this.worldType));
|
|
}
|
|
catch (RealmsServiceException e) {
|
|
return Either.right((Object)e);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void render(GuiGraphics graphics, int xm, int ym, float a) {
|
|
super.render(graphics, xm, ym, a);
|
|
this.currentLink = null;
|
|
if (this.noTemplatesMessage != null) {
|
|
this.renderMultilineMessage(graphics, xm, ym, this.noTemplatesMessage);
|
|
}
|
|
}
|
|
|
|
private void renderMultilineMessage(GuiGraphics graphics, int xm, int ym, List<TextRenderingUtils.Line> noTemplatesMessage) {
|
|
for (int i = 0; i < noTemplatesMessage.size(); ++i) {
|
|
TextRenderingUtils.Line line = noTemplatesMessage.get(i);
|
|
int lineY = RealmsSelectWorldTemplateScreen.row(4 + i);
|
|
int lineWidth = line.segments.stream().mapToInt(s -> this.font.width(s.renderedText())).sum();
|
|
int startX = this.width / 2 - lineWidth / 2;
|
|
for (TextRenderingUtils.LineSegment segment : line.segments) {
|
|
int color = segment.isLink() ? -13408581 : -1;
|
|
String text = segment.renderedText();
|
|
graphics.drawString(this.font, text, startX, lineY, color);
|
|
int endX = startX + this.font.width(text);
|
|
if (segment.isLink() && xm > startX && xm < endX && ym > lineY - 3 && ym < lineY + 8) {
|
|
graphics.setTooltipForNextFrame(Component.literal(segment.getLinkUrl()), xm, ym);
|
|
this.currentLink = segment.getLinkUrl();
|
|
}
|
|
startX = endX;
|
|
}
|
|
}
|
|
}
|
|
|
|
private class WorldTemplateList
|
|
extends ObjectSelectionList<Entry> {
|
|
public WorldTemplateList() {
|
|
this(Collections.emptyList());
|
|
}
|
|
|
|
public WorldTemplateList(Iterable<WorldTemplate> templates) {
|
|
super(Minecraft.getInstance(), RealmsSelectWorldTemplateScreen.this.width, RealmsSelectWorldTemplateScreen.this.layout.getContentHeight(), RealmsSelectWorldTemplateScreen.this.layout.getHeaderHeight(), 46);
|
|
templates.forEach(this::addEntry);
|
|
}
|
|
|
|
public void addEntry(WorldTemplate template) {
|
|
this.addEntry(new Entry(template));
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
|
|
if (RealmsSelectWorldTemplateScreen.this.currentLink != null) {
|
|
ConfirmLinkScreen.confirmLinkNow((Screen)RealmsSelectWorldTemplateScreen.this, RealmsSelectWorldTemplateScreen.this.currentLink);
|
|
return true;
|
|
}
|
|
return super.mouseClicked(event, doubleClick);
|
|
}
|
|
|
|
@Override
|
|
public void setSelected(@Nullable Entry selected) {
|
|
super.setSelected(selected);
|
|
RealmsSelectWorldTemplateScreen.this.selectedTemplate = selected == null ? null : selected.template;
|
|
RealmsSelectWorldTemplateScreen.this.updateButtonStates();
|
|
}
|
|
|
|
@Override
|
|
public int getRowWidth() {
|
|
return 300;
|
|
}
|
|
|
|
public boolean isEmpty() {
|
|
return this.getItemCount() == 0;
|
|
}
|
|
|
|
public List<WorldTemplate> getTemplates() {
|
|
return this.children().stream().map(c -> c.template).collect(Collectors.toList());
|
|
}
|
|
}
|
|
|
|
private class Entry
|
|
extends ObjectSelectionList.Entry<Entry> {
|
|
private static final WidgetSprites WEBSITE_LINK_SPRITES = new WidgetSprites(Identifier.withDefaultNamespace("icon/link"), Identifier.withDefaultNamespace("icon/link_highlighted"));
|
|
private static final WidgetSprites TRAILER_LINK_SPRITES = new WidgetSprites(Identifier.withDefaultNamespace("icon/video_link"), Identifier.withDefaultNamespace("icon/video_link_highlighted"));
|
|
private static final Component PUBLISHER_LINK_TOOLTIP = Component.translatable("mco.template.info.tooltip");
|
|
private static final Component TRAILER_LINK_TOOLTIP = Component.translatable("mco.template.trailer.tooltip");
|
|
public final WorldTemplate template;
|
|
private @Nullable ImageButton websiteButton;
|
|
private @Nullable ImageButton trailerButton;
|
|
|
|
public Entry(WorldTemplate template) {
|
|
this.template = template;
|
|
if (!template.link().isBlank()) {
|
|
this.websiteButton = new ImageButton(15, 15, WEBSITE_LINK_SPRITES, ConfirmLinkScreen.confirmLink((Screen)RealmsSelectWorldTemplateScreen.this, template.link()), PUBLISHER_LINK_TOOLTIP);
|
|
this.websiteButton.setTooltip(Tooltip.create(PUBLISHER_LINK_TOOLTIP));
|
|
}
|
|
if (!template.trailer().isBlank()) {
|
|
this.trailerButton = new ImageButton(15, 15, TRAILER_LINK_SPRITES, ConfirmLinkScreen.confirmLink((Screen)RealmsSelectWorldTemplateScreen.this, template.trailer()), TRAILER_LINK_TOOLTIP);
|
|
this.trailerButton.setTooltip(Tooltip.create(TRAILER_LINK_TOOLTIP));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean mouseClicked(MouseButtonEvent event, boolean doubleClick) {
|
|
RealmsSelectWorldTemplateScreen.this.selectedTemplate = this.template;
|
|
RealmsSelectWorldTemplateScreen.this.updateButtonStates();
|
|
if (doubleClick && this.isFocused()) {
|
|
RealmsSelectWorldTemplateScreen.this.callback.accept(this.template);
|
|
}
|
|
if (this.websiteButton != null) {
|
|
this.websiteButton.mouseClicked(event, doubleClick);
|
|
}
|
|
if (this.trailerButton != null) {
|
|
this.trailerButton.mouseClicked(event, doubleClick);
|
|
}
|
|
return super.mouseClicked(event, doubleClick);
|
|
}
|
|
|
|
@Override
|
|
public void renderContent(GuiGraphics graphics, int mouseX, int mouseY, boolean hovered, float a) {
|
|
graphics.blit(RenderPipelines.GUI_TEXTURED, RealmsTextureManager.worldTemplate(this.template.id(), this.template.image()), this.getContentX() + 1, this.getContentY() + 1 + 1, 0.0f, 0.0f, 38, 38, 38, 38);
|
|
graphics.blitSprite(RenderPipelines.GUI_TEXTURED, SLOT_FRAME_SPRITE, this.getContentX(), this.getContentY() + 1, 40, 40);
|
|
int padding = 5;
|
|
int versionTextWidth = RealmsSelectWorldTemplateScreen.this.font.width(this.template.version());
|
|
if (this.websiteButton != null) {
|
|
this.websiteButton.setPosition(this.getContentRight() - versionTextWidth - this.websiteButton.getWidth() - 10, this.getContentY());
|
|
this.websiteButton.render(graphics, mouseX, mouseY, a);
|
|
}
|
|
if (this.trailerButton != null) {
|
|
this.trailerButton.setPosition(this.getContentRight() - versionTextWidth - this.trailerButton.getWidth() * 2 - 15, this.getContentY());
|
|
this.trailerButton.render(graphics, mouseX, mouseY, a);
|
|
}
|
|
int textX = this.getContentX() + 45 + 20;
|
|
int textY = this.getContentY() + 5;
|
|
graphics.drawString(RealmsSelectWorldTemplateScreen.this.font, this.template.name(), textX, textY, -1);
|
|
graphics.drawString(RealmsSelectWorldTemplateScreen.this.font, this.template.version(), this.getContentRight() - versionTextWidth - 5, textY, -6250336);
|
|
graphics.drawString(RealmsSelectWorldTemplateScreen.this.font, this.template.author(), textX, textY + ((RealmsSelectWorldTemplateScreen)RealmsSelectWorldTemplateScreen.this).font.lineHeight + 5, -6250336);
|
|
if (!this.template.recommendedPlayers().isBlank()) {
|
|
graphics.drawString(RealmsSelectWorldTemplateScreen.this.font, this.template.recommendedPlayers(), textX, this.getContentBottom() - ((RealmsSelectWorldTemplateScreen)RealmsSelectWorldTemplateScreen.this).font.lineHeight / 2 - 5, -8355712);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public Component getNarration() {
|
|
Component entryName = CommonComponents.joinLines(Component.literal(this.template.name()), Component.translatable("mco.template.select.narrate.authors", this.template.author()), Component.literal(this.template.recommendedPlayers()), Component.translatable("mco.template.select.narrate.version", this.template.version()));
|
|
return Component.translatable("narrator.select", entryName);
|
|
}
|
|
}
|
|
}
|
|
|