158 lines
6.5 KiB
Java
158 lines
6.5 KiB
Java
package com.mojang.realmsclient.util.task;
|
|
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.realmsclient.client.RealmsClient;
|
|
import com.mojang.realmsclient.dto.RealmsServer;
|
|
import com.mojang.realmsclient.dto.RealmsServerAddress;
|
|
import com.mojang.realmsclient.exception.RealmsServiceException;
|
|
import com.mojang.realmsclient.exception.RetryCallException;
|
|
import com.mojang.realmsclient.gui.screens.RealmsBrokenWorldScreen;
|
|
import com.mojang.realmsclient.gui.screens.RealmsGenericErrorScreen;
|
|
import com.mojang.realmsclient.gui.screens.RealmsLongRunningMcoTaskScreen;
|
|
import com.mojang.realmsclient.gui.screens.RealmsLongRunningMcoTickTaskScreen;
|
|
import com.mojang.realmsclient.gui.screens.RealmsPopups;
|
|
import com.mojang.realmsclient.gui.screens.RealmsTermsScreen;
|
|
import java.net.URL;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.util.Objects;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.CancellationException;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.concurrent.TimeoutException;
|
|
import java.util.function.Function;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.components.PopupScreen;
|
|
import net.minecraft.client.gui.screens.GenericMessageScreen;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.client.resources.server.DownloadedPackSource;
|
|
import net.minecraft.network.chat.Component;
|
|
import org.slf4j.Logger;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class GetServerDetailsTask extends LongRunningTask {
|
|
private static final Component APPLYING_PACK_TEXT = Component.translatable("multiplayer.applyingPack");
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final Component TITLE = Component.translatable("mco.connect.connecting");
|
|
private final RealmsServer server;
|
|
private final Screen lastScreen;
|
|
|
|
public GetServerDetailsTask(Screen lastScreen, RealmsServer server) {
|
|
this.lastScreen = lastScreen;
|
|
this.server = server;
|
|
}
|
|
|
|
public void run() {
|
|
RealmsServerAddress realmsServerAddress;
|
|
try {
|
|
realmsServerAddress = this.fetchServerAddress();
|
|
} catch (CancellationException var4) {
|
|
LOGGER.info("User aborted connecting to realms");
|
|
return;
|
|
} catch (RealmsServiceException var5) {
|
|
switch (var5.realmsError.errorCode()) {
|
|
case 6002:
|
|
setScreen(new RealmsTermsScreen(this.lastScreen, this.server));
|
|
return;
|
|
case 6006:
|
|
boolean bl = Minecraft.getInstance().isLocalPlayer(this.server.ownerUUID);
|
|
setScreen(
|
|
(Screen)(bl
|
|
? new RealmsBrokenWorldScreen(this.lastScreen, this.server.id, this.server.isMinigameActive())
|
|
: new RealmsGenericErrorScreen(
|
|
Component.translatable("mco.brokenworld.nonowner.title"), Component.translatable("mco.brokenworld.nonowner.error"), this.lastScreen
|
|
))
|
|
);
|
|
return;
|
|
default:
|
|
this.error(var5);
|
|
LOGGER.error("Couldn't connect to world", (Throwable)var5);
|
|
return;
|
|
}
|
|
} catch (TimeoutException var6) {
|
|
this.error(Component.translatable("mco.errorMessage.connectionFailure"));
|
|
return;
|
|
} catch (Exception var7) {
|
|
LOGGER.error("Couldn't connect to world", (Throwable)var7);
|
|
this.error(var7);
|
|
return;
|
|
}
|
|
|
|
if (realmsServerAddress.address == null) {
|
|
this.error(Component.translatable("mco.errorMessage.connectionFailure"));
|
|
} else {
|
|
boolean bl2 = realmsServerAddress.resourcePackUrl != null && realmsServerAddress.resourcePackHash != null;
|
|
Screen screen = (Screen)(bl2
|
|
? this.resourcePackDownloadConfirmationScreen(realmsServerAddress, generatePackId(this.server), this::connectScreen)
|
|
: this.connectScreen(realmsServerAddress));
|
|
setScreen(screen);
|
|
}
|
|
}
|
|
|
|
private static UUID generatePackId(RealmsServer realmsServer) {
|
|
return realmsServer.minigameName != null
|
|
? UUID.nameUUIDFromBytes(("minigame:" + realmsServer.minigameName).getBytes(StandardCharsets.UTF_8))
|
|
: UUID.nameUUIDFromBytes(
|
|
("realms:" + (String)Objects.requireNonNullElse(realmsServer.name, "") + ":" + realmsServer.activeSlot).getBytes(StandardCharsets.UTF_8)
|
|
);
|
|
}
|
|
|
|
@Override
|
|
public Component getTitle() {
|
|
return TITLE;
|
|
}
|
|
|
|
private RealmsServerAddress fetchServerAddress() throws RealmsServiceException, TimeoutException, CancellationException {
|
|
RealmsClient realmsClient = RealmsClient.getOrCreate();
|
|
|
|
for (int i = 0; i < 40; i++) {
|
|
if (this.aborted()) {
|
|
throw new CancellationException();
|
|
}
|
|
|
|
try {
|
|
return realmsClient.join(this.server.id);
|
|
} catch (RetryCallException var4) {
|
|
pause(var4.delaySeconds);
|
|
}
|
|
}
|
|
|
|
throw new TimeoutException();
|
|
}
|
|
|
|
public RealmsLongRunningMcoTaskScreen connectScreen(RealmsServerAddress serverAddress) {
|
|
return new RealmsLongRunningMcoTickTaskScreen(this.lastScreen, new ConnectTask(this.lastScreen, this.server, serverAddress));
|
|
}
|
|
|
|
private PopupScreen resourcePackDownloadConfirmationScreen(RealmsServerAddress serverAddress, UUID packId, Function<RealmsServerAddress, Screen> connectScreen) {
|
|
Component component = Component.translatable("mco.configure.world.resourcepack.question");
|
|
return RealmsPopups.infoPopupScreen(this.lastScreen, component, popupScreen -> {
|
|
setScreen(new GenericMessageScreen(APPLYING_PACK_TEXT));
|
|
this.scheduleResourcePackDownload(serverAddress, packId).thenRun(() -> setScreen((Screen)connectScreen.apply(serverAddress))).exceptionally(throwable -> {
|
|
Minecraft.getInstance().getDownloadedPackSource().cleanupAfterDisconnect();
|
|
LOGGER.error("Failed to download resource pack from {}", serverAddress, throwable);
|
|
setScreen(new RealmsGenericErrorScreen(Component.translatable("mco.download.resourcePack.fail"), this.lastScreen));
|
|
return null;
|
|
});
|
|
});
|
|
}
|
|
|
|
private CompletableFuture<?> scheduleResourcePackDownload(RealmsServerAddress serverAddress, UUID id) {
|
|
try {
|
|
if (serverAddress.resourcePackUrl == null) {
|
|
return CompletableFuture.failedFuture(new IllegalStateException("resourcePackUrl was null"));
|
|
} else if (serverAddress.resourcePackHash == null) {
|
|
return CompletableFuture.failedFuture(new IllegalStateException("resourcePackHash was null"));
|
|
} else {
|
|
DownloadedPackSource downloadedPackSource = Minecraft.getInstance().getDownloadedPackSource();
|
|
CompletableFuture<Void> completableFuture = downloadedPackSource.waitForPackFeedback(id);
|
|
downloadedPackSource.allowServerPacks();
|
|
downloadedPackSource.pushPack(id, new URL(serverAddress.resourcePackUrl), serverAddress.resourcePackHash);
|
|
return completableFuture;
|
|
}
|
|
} catch (Exception var5) {
|
|
return CompletableFuture.failedFuture(var5);
|
|
}
|
|
}
|
|
}
|