285 lines
9.9 KiB
Java
285 lines
9.9 KiB
Java
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.RealmsWorldOptions;
|
|
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.atomic.AtomicReference;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
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.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.realms.RealmsScreen;
|
|
import net.minecraft.world.level.storage.LevelSummary;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
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;
|
|
@Nullable
|
|
private final RealmCreationTask realmCreationTask;
|
|
private final long realmId;
|
|
private final int slotId;
|
|
final AtomicReference<RealmsWorldUpload> currentUpload = new AtomicReference();
|
|
private final UploadStatus uploadStatus;
|
|
private final RateLimiter narrationRateLimiter;
|
|
@Nullable
|
|
private volatile Component[] errorMessage;
|
|
private volatile Component status = Component.translatable("mco.upload.preparing");
|
|
@Nullable
|
|
private volatile String progress;
|
|
private volatile boolean cancelled;
|
|
private volatile boolean uploadFinished;
|
|
private volatile boolean showDots = true;
|
|
private volatile boolean uploadStarted;
|
|
@Nullable
|
|
private Button backButton;
|
|
@Nullable
|
|
private 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(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 {
|
|
List<LongRunningTask> list = new ArrayList();
|
|
if (this.realmCreationTask != null) {
|
|
list.add(this.realmCreationTask);
|
|
}
|
|
|
|
list.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, (LongRunningTask[])list.toArray(new LongRunningTask[0])));
|
|
}
|
|
}
|
|
|
|
this.layout.visitWidgets(guiEventListener -> {
|
|
AbstractWidget var10000 = this.addRenderableWidget(guiEventListener);
|
|
});
|
|
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 = (RealmsWorldUpload)this.currentUpload.get();
|
|
if (realmsWorldUpload != null) {
|
|
realmsWorldUpload.cancel();
|
|
} else {
|
|
this.minecraft.setScreen(this.lastScreen);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
|
if (keyCode == 256) {
|
|
if (this.showDots) {
|
|
this.onCancel();
|
|
} else {
|
|
this.onBack();
|
|
}
|
|
|
|
return true;
|
|
} else {
|
|
return super.keyPressed(keyCode, scanCode, modifiers);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
|
super.render(guiGraphics, mouseX, mouseY, partialTick);
|
|
if (!this.uploadFinished && this.uploadStatus.uploadStarted() && this.uploadStatus.uploadCompleted() && this.cancelButton != null) {
|
|
this.status = VERIFYING_TEXT;
|
|
this.cancelButton.active = false;
|
|
}
|
|
|
|
guiGraphics.drawCenteredString(this.font, this.status, this.width / 2, 50, -1);
|
|
if (this.showDots) {
|
|
guiGraphics.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(guiGraphics);
|
|
this.drawUploadSpeed(guiGraphics);
|
|
}
|
|
|
|
Component[] components = this.errorMessage;
|
|
if (components != null) {
|
|
for (int i = 0; i < components.length; i++) {
|
|
guiGraphics.drawCenteredString(this.font, components[i], this.width / 2, 110 + 12 * i, -65536);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void drawProgressBar(GuiGraphics guiGraphics) {
|
|
double d = this.uploadStatus.getPercentage();
|
|
this.progress = String.format(Locale.ROOT, "%.1f", d * 100.0);
|
|
int i = (this.width - 200) / 2;
|
|
int j = i + (int)Math.round(200.0 * d);
|
|
guiGraphics.fill(i - 1, 79, j + 1, 96, -1);
|
|
guiGraphics.fill(i, 80, j, 95, -8355712);
|
|
guiGraphics.drawCenteredString(this.font, Component.translatable("mco.upload.percent", this.progress), this.width / 2, 84, -1);
|
|
}
|
|
|
|
private void drawUploadSpeed(GuiGraphics guiGraphics) {
|
|
this.drawUploadSpeed0(guiGraphics, this.uploadStatus.getBytesPerSecond());
|
|
}
|
|
|
|
private void drawUploadSpeed0(GuiGraphics guiGraphics, long bytesPerSecond) {
|
|
String string = this.progress;
|
|
if (bytesPerSecond > 0L && string != null) {
|
|
int i = this.font.width(string);
|
|
String string2 = "(" + Unit.humanReadable(bytesPerSecond) + "/s)";
|
|
guiGraphics.drawString(this.font, string2, this.width / 2 + i / 2 + 15, 84, -1);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
this.tickCount++;
|
|
this.uploadStatus.refreshBytesPerSecond();
|
|
if (this.narrationRateLimiter.tryAcquire(1)) {
|
|
Component component = this.createProgressNarrationMessage();
|
|
this.minecraft.getNarrator().sayNow(component);
|
|
}
|
|
}
|
|
|
|
private Component createProgressNarrationMessage() {
|
|
List<Component> list = Lists.<Component>newArrayList();
|
|
list.add(this.status);
|
|
if (this.progress != null) {
|
|
list.add(Component.translatable("mco.upload.percent", this.progress));
|
|
}
|
|
|
|
Component[] components = this.errorMessage;
|
|
if (components != null) {
|
|
list.addAll(Arrays.asList(components));
|
|
}
|
|
|
|
return CommonComponents.joinLines(list);
|
|
}
|
|
|
|
private void upload() {
|
|
Path path = this.minecraft.gameDirectory.toPath().resolve("saves").resolve(this.selectedLevel.getLevelId());
|
|
RealmsWorldOptions realmsWorldOptions = RealmsWorldOptions.createFromSettings(
|
|
this.selectedLevel.getSettings(), true, this.selectedLevel.levelVersion().minecraftVersionName()
|
|
);
|
|
RealmsWorldUpload realmsWorldUpload = new RealmsWorldUpload(path, realmsWorldOptions, this.minecraft.getUser(), this.realmId, this.slotId, this);
|
|
if (!this.currentUpload.compareAndSet(null, realmsWorldUpload)) {
|
|
throw new IllegalStateException("Tried to start uploading but was already uploading");
|
|
} else {
|
|
realmsWorldUpload.packAndUpload().handleAsync((object, throwable) -> {
|
|
if (throwable != null) {
|
|
if (throwable instanceof CompletionException completionException) {
|
|
throwable = completionException.getCause();
|
|
}
|
|
|
|
if (throwable instanceof RealmsUploadException realmsUploadException) {
|
|
if (realmsUploadException.getStatusMessage() != null) {
|
|
this.status = realmsUploadException.getStatusMessage();
|
|
}
|
|
|
|
this.setErrorMessage(realmsUploadException.getErrorMessages());
|
|
} else {
|
|
this.status = Component.translatable("mco.upload.failed", throwable.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;
|
|
}, this.minecraft);
|
|
}
|
|
}
|
|
|
|
private void setErrorMessage(@Nullable Component... errorMessage) {
|
|
this.errorMessage = errorMessage;
|
|
}
|
|
|
|
@Override
|
|
public UploadStatus getUploadStatus() {
|
|
return this.uploadStatus;
|
|
}
|
|
|
|
@Override
|
|
public void setUploading() {
|
|
this.status = Component.translatable("mco.upload.uploading", this.selectedLevel.getLevelName());
|
|
}
|
|
}
|