minecraft-src/com/mojang/realmsclient/RealmsAvailability.java
2025-07-04 03:45:38 +03:00

99 lines
3.6 KiB
Java

package com.mojang.realmsclient;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.client.RealmsClient;
import com.mojang.realmsclient.exception.RealmsServiceException;
import com.mojang.realmsclient.gui.screens.RealmsClientOutdatedScreen;
import com.mojang.realmsclient.gui.screens.RealmsGenericErrorScreen;
import com.mojang.realmsclient.gui.screens.RealmsParentalConsentScreen;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.User;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@Environment(EnvType.CLIENT)
public class RealmsAvailability {
private static final Logger LOGGER = LogUtils.getLogger();
@Nullable
private static CompletableFuture<RealmsAvailability.Result> future;
public static CompletableFuture<RealmsAvailability.Result> get() {
if (future == null || shouldRefresh(future)) {
future = check();
}
return future;
}
private static boolean shouldRefresh(CompletableFuture<RealmsAvailability.Result> future) {
RealmsAvailability.Result result = (RealmsAvailability.Result)future.getNow(null);
return result != null && result.exception() != null;
}
private static CompletableFuture<RealmsAvailability.Result> check() {
User user = Minecraft.getInstance().getUser();
return user.getType() != User.Type.MSA
? CompletableFuture.completedFuture(new RealmsAvailability.Result(RealmsAvailability.Type.AUTHENTICATION_ERROR))
: CompletableFuture.supplyAsync(
() -> {
RealmsClient realmsClient = RealmsClient.getOrCreate();
try {
if (realmsClient.clientCompatible() != RealmsClient.CompatibleVersionResponse.COMPATIBLE) {
return new RealmsAvailability.Result(RealmsAvailability.Type.INCOMPATIBLE_CLIENT);
} else {
return !realmsClient.hasParentalConsent()
? new RealmsAvailability.Result(RealmsAvailability.Type.NEEDS_PARENTAL_CONSENT)
: new RealmsAvailability.Result(RealmsAvailability.Type.SUCCESS);
}
} catch (RealmsServiceException var2) {
LOGGER.error("Couldn't connect to realms", (Throwable)var2);
return var2.realmsError.errorCode() == 401
? new RealmsAvailability.Result(RealmsAvailability.Type.AUTHENTICATION_ERROR)
: new RealmsAvailability.Result(var2);
}
},
Util.ioPool()
);
}
@Environment(EnvType.CLIENT)
public record Result(RealmsAvailability.Type type, @Nullable RealmsServiceException exception) {
public Result(RealmsAvailability.Type type) {
this(type, null);
}
public Result(RealmsServiceException exception) {
this(RealmsAvailability.Type.UNEXPECTED_ERROR, exception);
}
@Nullable
public Screen createErrorScreen(Screen lastScreen) {
return (Screen)(switch (this.type) {
case SUCCESS -> null;
case INCOMPATIBLE_CLIENT -> new RealmsClientOutdatedScreen(lastScreen);
case NEEDS_PARENTAL_CONSENT -> new RealmsParentalConsentScreen(lastScreen);
case AUTHENTICATION_ERROR -> new RealmsGenericErrorScreen(
Component.translatable("mco.error.invalid.session.title"), Component.translatable("mco.error.invalid.session.message"), lastScreen
);
case UNEXPECTED_ERROR -> new RealmsGenericErrorScreen((RealmsServiceException)Objects.requireNonNull(this.exception), lastScreen);
});
}
}
@Environment(EnvType.CLIENT)
public static enum Type {
SUCCESS,
INCOMPATIBLE_CLIENT,
NEEDS_PARENTAL_CONSENT,
AUTHENTICATION_ERROR,
UNEXPECTED_ERROR;
}
}