minecraft-source/src/com/mojang/realmsclient/gui/screens/RealmsDownloadLatestWorldSc...

304 lines
13 KiB
Java

package com.mojang.realmsclient.gui.screens;
import org.apache.logging.log4j.LogManager;
import java.util.concurrent.TimeUnit;
import net.minecraft.Util;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.systems.RenderSystem;
import java.util.Locale;
import net.minecraft.network.chat.FormattedText;
import com.mojang.blaze3d.vertex.PoseStack;
import java.util.List;
import net.minecraft.realms.NarrationHelper;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import net.minecraft.network.chat.TextComponent;
import com.google.common.collect.Lists;
import com.mojang.realmsclient.client.FileDownload;
import com.mojang.realmsclient.Unit;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.TranslatableComponent;
import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
import net.minecraft.client.gui.components.Button;
import com.google.common.util.concurrent.RateLimiter;
import net.minecraft.network.chat.Component;
import com.mojang.realmsclient.dto.WorldDownload;
import net.minecraft.client.gui.screens.Screen;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.logging.log4j.Logger;
import net.minecraft.realms.RealmsScreen;
public class RealmsDownloadLatestWorldScreen extends RealmsScreen {
private static final Logger LOGGER;
private static final ReentrantLock DOWNLOAD_LOCK;
private final Screen lastScreen;
private final WorldDownload worldDownload;
private final Component downloadTitle;
private final RateLimiter narrationRateLimiter;
private Button cancelButton;
private final String worldName;
private final DownloadStatus downloadStatus;
private volatile Component errorMessage;
private volatile Component status;
private volatile String progress;
private volatile boolean cancelled;
private volatile boolean showDots;
private volatile boolean finished;
private volatile boolean extracting;
private Long previousWrittenBytes;
private Long previousTimeSnapshot;
private long bytesPersSecond;
private int animTick;
private static final String[] DOTS;
private int dotIndex;
private boolean checked;
private final BooleanConsumer callback;
public RealmsDownloadLatestWorldScreen(final Screen dqs, final WorldDownload djc, final String string, final BooleanConsumer booleanConsumer) {
this.status = new TranslatableComponent("mco.download.preparing");
this.showDots = true;
this.callback = booleanConsumer;
this.lastScreen = dqs;
this.worldName = string;
this.worldDownload = djc;
this.downloadStatus = new DownloadStatus();
this.downloadTitle = new TranslatableComponent("mco.download.title");
this.narrationRateLimiter = RateLimiter.create(0.10000000149011612);
}
public void init() {
this.minecraft.keyboardHandler.setSendRepeatsToGui(true);
this.cancelButton = this.<Button>addButton(new Button(this.width / 2 - 100, this.height - 42, 200, 20, CommonComponents.GUI_CANCEL, dni -> {
this.cancelled = true;
this.backButtonClicked();
return;
}));
this.checkDownloadSize();
}
private void checkDownloadSize() {
if (this.finished) {
return;
}
if (!this.checked && this.getContentLength(this.worldDownload.downloadLink) >= 5368709120L) {
final Component mr2 = new TranslatableComponent("mco.download.confirmation.line1", new Object[] { Unit.humanReadable(5368709120L) });
final Component mr3 = new TranslatableComponent("mco.download.confirmation.line2");
this.minecraft.setScreen(new RealmsLongConfirmationScreen(boolean1 -> {
this.checked = true;
this.minecraft.setScreen(this);
this.downloadSave();
}, RealmsLongConfirmationScreen.Type.Warning, mr2, mr3, false));
}
else {
this.downloadSave();
}
}
private long getContentLength(final String string) {
final FileDownload dhx3 = new FileDownload();
return dhx3.contentLength(string);
}
@Override
public void tick() {
super.tick();
++this.animTick;
if (this.status != null && this.narrationRateLimiter.tryAcquire(1)) {
final List<Component> list2 = Lists.newArrayList();
list2.add(this.downloadTitle);
list2.add(this.status);
if (this.progress != null) {
list2.add(new TextComponent(this.progress + "%"));
list2.add(new TextComponent(Unit.humanReadable(this.bytesPersSecond) + "/s"));
}
if (this.errorMessage != null) {
list2.add(this.errorMessage);
}
final String string3 = list2.stream().map(Component::getString).collect(Collectors.joining("\n"));
NarrationHelper.now(string3);
}
}
@Override
public boolean keyPressed(final int integer1, final int integer2, final int integer3) {
if (integer1 == 256) {
this.cancelled = true;
this.backButtonClicked();
return true;
}
return super.keyPressed(integer1, integer2, integer3);
}
private void backButtonClicked() {
if (this.finished && this.callback != null && this.errorMessage == null) {
this.callback.accept(true);
}
this.minecraft.setScreen(this.lastScreen);
}
@Override
public void render(final PoseStack dhl, final int integer2, final int integer3, final float float4) {
this.renderBackground(dhl);
if (this.extracting && !this.finished) {
this.status = new TranslatableComponent("mco.download.extracting");
}
this.drawCenteredString(dhl, this.font, this.downloadTitle, this.width / 2, 20, 16777215);
this.drawCenteredString(dhl, this.font, this.status, this.width / 2, 50, 16777215);
if (this.showDots) {
this.drawDots(dhl);
}
if (this.downloadStatus.bytesWritten != 0L && !this.cancelled) {
this.drawProgressBar(dhl);
this.drawDownloadSpeed(dhl);
}
if (this.errorMessage != null) {
this.drawCenteredString(dhl, this.font, this.errorMessage, this.width / 2, 110, 16711680);
}
super.render(dhl, integer2, integer3, float4);
}
private void drawDots(final PoseStack dhl) {
final int integer3 = this.font.width(this.status);
if (this.animTick % 10 == 0) {
++this.dotIndex;
}
this.font.draw(dhl, RealmsDownloadLatestWorldScreen.DOTS[this.dotIndex % RealmsDownloadLatestWorldScreen.DOTS.length], (float)(this.width / 2 + integer3 / 2 + 5), 50.0f, 16777215);
}
private void drawProgressBar(final PoseStack dhl) {
final double double3 = this.downloadStatus.bytesWritten / (double)this.downloadStatus.totalBytes * 100.0;
this.progress = String.format(Locale.ROOT, "%.1f", double3);
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableTexture();
final Tesselator dhn5 = Tesselator.getInstance();
final BufferBuilder dhg6 = dhn5.getBuilder();
dhg6.begin(7, DefaultVertexFormat.POSITION_COLOR);
final double double4 = this.width / 2 - 100;
final double double5 = 0.5;
dhg6.vertex(double4 - 0.5, 95.5, 0.0).color(217, 210, 210, 255).endVertex();
dhg6.vertex(double4 + 200.0 * double3 / 100.0 + 0.5, 95.5, 0.0).color(217, 210, 210, 255).endVertex();
dhg6.vertex(double4 + 200.0 * double3 / 100.0 + 0.5, 79.5, 0.0).color(217, 210, 210, 255).endVertex();
dhg6.vertex(double4 - 0.5, 79.5, 0.0).color(217, 210, 210, 255).endVertex();
dhg6.vertex(double4, 95.0, 0.0).color(128, 128, 128, 255).endVertex();
dhg6.vertex(double4 + 200.0 * double3 / 100.0, 95.0, 0.0).color(128, 128, 128, 255).endVertex();
dhg6.vertex(double4 + 200.0 * double3 / 100.0, 80.0, 0.0).color(128, 128, 128, 255).endVertex();
dhg6.vertex(double4, 80.0, 0.0).color(128, 128, 128, 255).endVertex();
dhn5.end();
RenderSystem.enableTexture();
this.drawCenteredString(dhl, this.font, this.progress + " %", this.width / 2, 84, 16777215);
}
private void drawDownloadSpeed(final PoseStack dhl) {
if (this.animTick % 20 == 0) {
if (this.previousWrittenBytes != null) {
long long3 = Util.getMillis() - this.previousTimeSnapshot;
if (long3 == 0L) {
long3 = 1L;
}
this.drawDownloadSpeed0(dhl, this.bytesPersSecond = 1000L * (this.downloadStatus.bytesWritten - this.previousWrittenBytes) / long3);
}
this.previousWrittenBytes = this.downloadStatus.bytesWritten;
this.previousTimeSnapshot = Util.getMillis();
}
else {
this.drawDownloadSpeed0(dhl, this.bytesPersSecond);
}
}
private void drawDownloadSpeed0(final PoseStack dhl, final long long2) {
if (long2 > 0L) {
final int integer5 = this.font.width(this.progress);
final String string6 = "(" + Unit.humanReadable(long2) + "/s)";
this.font.draw(dhl, string6, (float)(this.width / 2 + integer5 / 2 + 15), 84.0f, 16777215);
}
}
private void downloadSave() {
final TranslatableComponent status;
FileDownload dhx2;
new Thread(() -> {
try {
if (!RealmsDownloadLatestWorldScreen.DOWNLOAD_LOCK.tryLock(1L, TimeUnit.SECONDS)) {
this.status = new TranslatableComponent("mco.download.failed");
}
else if (this.cancelled) {
this.downloadCancelled();
}
else {
new TranslatableComponent("mco.download.downloading", new Object[] { this.worldName });
this.status = status;
dhx2 = new FileDownload();
dhx2.contentLength(this.worldDownload.downloadLink);
dhx2.download(this.worldDownload, this.worldName, this.downloadStatus, this.minecraft.getLevelSource());
while (!dhx2.isFinished()) {
if (dhx2.isError()) {
dhx2.cancel();
this.errorMessage = new TranslatableComponent("mco.download.failed");
this.cancelButton.setMessage(CommonComponents.GUI_DONE);
return;
}
else {
if (dhx2.isExtracting()) {
this.extracting = true;
}
if (this.cancelled) {
dhx2.cancel();
this.downloadCancelled();
return;
}
else {
try {
Thread.sleep(500L);
}
catch (InterruptedException interruptedException3) {
RealmsDownloadLatestWorldScreen.LOGGER.error("Failed to check Realms backup download status");
}
}
}
}
this.finished = true;
this.status = new TranslatableComponent("mco.download.done");
this.cancelButton.setMessage(CommonComponents.GUI_DONE);
}
}
catch (InterruptedException interruptedException4) {
RealmsDownloadLatestWorldScreen.LOGGER.error("Could not acquire upload lock");
}
catch (Exception exception2) {
this.errorMessage = new TranslatableComponent("mco.download.failed");
exception2.printStackTrace();
}
finally {
if (RealmsDownloadLatestWorldScreen.DOWNLOAD_LOCK.isHeldByCurrentThread()) {
RealmsDownloadLatestWorldScreen.DOWNLOAD_LOCK.unlock();
this.showDots = false;
this.finished = true;
}
}
}).start();
}
private void downloadCancelled() {
this.status = new TranslatableComponent("mco.download.cancelled");
}
static {
LOGGER = LogManager.getLogger();
DOWNLOAD_LOCK = new ReentrantLock();
DOTS = new String[] { "", ".", ". .", ". . ." };
}
public class DownloadStatus {
public volatile Long bytesWritten;
public volatile Long totalBytes;
public DownloadStatus() {
this.bytesWritten = 0L;
this.totalBytes = 0L;
}
}
}