/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Lists * com.google.common.util.concurrent.RateLimiter * org.jspecify.annotations.Nullable */ package com.mojang.realmsclient.gui.screens; import com.google.common.collect.Lists; import com.google.common.util.concurrent.RateLimiter; import com.mojang.realmsclient.RealmsMainScreen; import com.mojang.realmsclient.Unit; import com.mojang.realmsclient.client.UploadStatus; import com.mojang.realmsclient.client.worldupload.RealmsUploadException; import com.mojang.realmsclient.client.worldupload.RealmsWorldUpload; import com.mojang.realmsclient.client.worldupload.RealmsWorldUploadStatusTracker; import com.mojang.realmsclient.dto.RealmsSetting; import com.mojang.realmsclient.dto.RealmsSlot; import com.mojang.realmsclient.dto.RealmsWorldOptions; import com.mojang.realmsclient.gui.screens.RealmsLongRunningMcoTaskScreen; import com.mojang.realmsclient.gui.screens.RealmsResetWorldScreen; import com.mojang.realmsclient.gui.screens.configuration.RealmsConfigureWorldScreen; import com.mojang.realmsclient.util.task.LongRunningTask; import com.mojang.realmsclient.util.task.RealmCreationTask; import com.mojang.realmsclient.util.task.SwitchSlotTask; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Locale; import java.util.concurrent.CompletionException; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicReference; import net.minecraft.client.GameNarrator; 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.layouts.HeaderAndFooterLayout; import net.minecraft.client.gui.screens.TitleScreen; import net.minecraft.client.input.KeyEvent; import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.realms.RealmsScreen; import net.minecraft.world.level.storage.LevelSummary; import org.jspecify.annotations.Nullable; public class RealmsUploadScreen extends RealmsScreen implements RealmsWorldUploadStatusTracker { private static final int BAR_WIDTH = 200; private static final int BAR_TOP = 80; private static final int BAR_BOTTOM = 95; private static final int BAR_BORDER = 1; private static final String[] DOTS = new String[]{"", ".", ". .", ". . ."}; private static final Component VERIFYING_TEXT = Component.translatable("mco.upload.verifying"); private final RealmsResetWorldScreen lastScreen; private final LevelSummary selectedLevel; private final @Nullable RealmCreationTask realmCreationTask; private final long realmId; private final int slotId; final AtomicReference<@Nullable RealmsWorldUpload> currentUpload = new AtomicReference(); private final UploadStatus uploadStatus; private final RateLimiter narrationRateLimiter; private volatile Component @Nullable [] errorMessage; private volatile Component status = Component.translatable("mco.upload.preparing"); private volatile @Nullable String progress; private volatile boolean cancelled; private volatile boolean uploadFinished; private volatile boolean showDots = true; private volatile boolean uploadStarted; private @Nullable Button backButton; private @Nullable Button cancelButton; private int tickCount; private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this); public RealmsUploadScreen(@Nullable RealmCreationTask realmCreationTask, long realmId, int slotId, RealmsResetWorldScreen lastScreen, LevelSummary selectedLevel) { super(GameNarrator.NO_TITLE); this.realmCreationTask = realmCreationTask; this.realmId = realmId; this.slotId = slotId; this.lastScreen = lastScreen; this.selectedLevel = selectedLevel; this.uploadStatus = new UploadStatus(); this.narrationRateLimiter = RateLimiter.create((double)0.1f); } @Override public void init() { this.backButton = this.layout.addToFooter(Button.builder(CommonComponents.GUI_BACK, button -> this.onBack()).build()); this.backButton.visible = false; this.cancelButton = this.layout.addToFooter(Button.builder(CommonComponents.GUI_CANCEL, button -> this.onCancel()).build()); if (!this.uploadStarted) { if (this.lastScreen.slot == -1) { this.uploadStarted = true; this.upload(); } else { ArrayList tasks = new ArrayList(); if (this.realmCreationTask != null) { tasks.add(this.realmCreationTask); } tasks.add(new SwitchSlotTask(this.realmId, this.lastScreen.slot, () -> { if (!this.uploadStarted) { this.uploadStarted = true; this.minecraft.execute(() -> { this.minecraft.setScreen(this); this.upload(); }); } })); this.minecraft.setScreen(new RealmsLongRunningMcoTaskScreen(this.lastScreen, tasks.toArray(new LongRunningTask[0]))); } } this.layout.visitWidgets(x$0 -> { AbstractWidget cfr_ignored_0 = (AbstractWidget)this.addRenderableWidget(x$0); }); this.repositionElements(); } @Override protected void repositionElements() { this.layout.arrangeElements(); } private void onBack() { this.minecraft.setScreen(new RealmsConfigureWorldScreen(new RealmsMainScreen(new TitleScreen()), this.realmId)); } private void onCancel() { this.cancelled = true; RealmsWorldUpload realmsWorldUpload = this.currentUpload.get(); if (realmsWorldUpload != null) { realmsWorldUpload.cancel(); } else { this.minecraft.setScreen(this.lastScreen); } } @Override public boolean keyPressed(KeyEvent event) { if (event.key() == 256) { if (this.showDots) { this.onCancel(); } else { this.onBack(); } return true; } return super.keyPressed(event); } @Override public void render(GuiGraphics graphics, int xm, int ym, float a) { Component[] errorMessages; super.render(graphics, xm, ym, a); if (!this.uploadFinished && this.uploadStatus.uploadStarted() && this.uploadStatus.uploadCompleted() && this.cancelButton != null) { this.status = VERIFYING_TEXT; this.cancelButton.active = false; } graphics.drawCenteredString(this.font, this.status, this.width / 2, 50, -1); if (this.showDots) { graphics.drawString(this.font, DOTS[this.tickCount / 10 % DOTS.length], this.width / 2 + this.font.width(this.status) / 2 + 5, 50, -1); } if (this.uploadStatus.uploadStarted() && !this.cancelled) { this.drawProgressBar(graphics); this.drawUploadSpeed(graphics); } if ((errorMessages = this.errorMessage) != null) { for (int i = 0; i < errorMessages.length; ++i) { graphics.drawCenteredString(this.font, errorMessages[i], this.width / 2, 110 + 12 * i, -65536); } } } private void drawProgressBar(GuiGraphics graphics) { double percentage = this.uploadStatus.getPercentage(); this.progress = String.format(Locale.ROOT, "%.1f", percentage * 100.0); int left = (this.width - 200) / 2; int right = left + (int)Math.round(200.0 * percentage); graphics.fill(left - 1, 79, right + 1, 96, -1); graphics.fill(left, 80, right, 95, -8355712); graphics.drawCenteredString(this.font, Component.translatable("mco.upload.percent", this.progress), this.width / 2, 84, -1); } private void drawUploadSpeed(GuiGraphics graphics) { this.drawUploadSpeed0(graphics, this.uploadStatus.getBytesPerSecond()); } private void drawUploadSpeed0(GuiGraphics graphics, long bytesPerSecond) { String uploadProgress = this.progress; if (bytesPerSecond > 0L && uploadProgress != null) { int progressLength = this.font.width(uploadProgress); String stringPresentation = "(" + Unit.humanReadable(bytesPerSecond) + "/s)"; graphics.drawString(this.font, stringPresentation, this.width / 2 + progressLength / 2 + 15, 84, -1); } } @Override public void tick() { super.tick(); ++this.tickCount; this.uploadStatus.refreshBytesPerSecond(); if (this.narrationRateLimiter.tryAcquire(1)) { Component message = this.createProgressNarrationMessage(); this.minecraft.getNarrator().saySystemNow(message); } } private Component createProgressNarrationMessage() { Component[] errorMessages; ArrayList elements = Lists.newArrayList(); elements.add(this.status); if (this.progress != null) { elements.add(Component.translatable("mco.upload.percent", this.progress)); } if ((errorMessages = this.errorMessage) != null) { elements.addAll(Arrays.asList(errorMessages)); } return CommonComponents.joinLines(elements); } private void upload() { RealmsWorldOptions worldOptions; RealmsSlot realmsSlot; Path worldFolder = this.minecraft.gameDirectory.toPath().resolve("saves").resolve(this.selectedLevel.getLevelId()); RealmsWorldUpload newUpload = new RealmsWorldUpload(worldFolder, realmsSlot = new RealmsSlot(this.slotId, worldOptions = RealmsWorldOptions.createFromSettings(this.selectedLevel.getSettings(), this.selectedLevel.levelVersion().minecraftVersionName()), List.of(RealmsSetting.hardcoreSetting(this.selectedLevel.getSettings().hardcore()))), this.minecraft.getUser(), this.realmId, this); if (!this.currentUpload.compareAndSet(null, newUpload)) { throw new IllegalStateException("Tried to start uploading but was already uploading"); } newUpload.packAndUpload().handleAsync((result, exception) -> { if (exception != null) { RuntimeException e; if (exception instanceof CompletionException) { e = (CompletionException)exception; exception = e.getCause(); } if (exception instanceof RealmsUploadException) { e = (RealmsUploadException)exception; if (((RealmsUploadException)e).getStatusMessage() != null) { this.status = ((RealmsUploadException)e).getStatusMessage(); } this.setErrorMessage(((RealmsUploadException)e).getErrorMessages()); } else { this.status = Component.translatable("mco.upload.failed", exception.getMessage()); } } else { this.status = Component.translatable("mco.upload.done"); if (this.backButton != null) { this.backButton.setMessage(CommonComponents.GUI_DONE); } } this.uploadFinished = true; this.showDots = false; if (this.backButton != null) { this.backButton.visible = true; } if (this.cancelButton != null) { this.cancelButton.visible = false; } this.currentUpload.set(null); return null; }, (Executor)this.minecraft); } private void setErrorMessage(Component ... messages) { this.errorMessage = messages; } @Override public UploadStatus getUploadStatus() { return this.uploadStatus; } @Override public void setUploading() { this.status = Component.translatable("mco.upload.uploading", this.selectedLevel.getLevelName()); } }