281 lines
12 KiB
Java
281 lines
12 KiB
Java
/*
|
|
* 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<LongRunningTask> tasks = new ArrayList<LongRunningTask>();
|
|
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());
|
|
}
|
|
}
|
|
|