168 lines
9.0 KiB
Java
168 lines
9.0 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* it.unimi.dsi.fastutil.booleans.BooleanConsumer
|
|
* org.jspecify.annotations.Nullable
|
|
* org.slf4j.Logger
|
|
*/
|
|
package net.minecraft.client.gui.screens;
|
|
|
|
import com.mojang.logging.LogUtils;
|
|
import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.lang.invoke.LambdaMetafactory;
|
|
import java.time.Instant;
|
|
import java.time.ZoneId;
|
|
import java.time.ZonedDateTime;
|
|
import net.minecraft.ChatFormatting;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.gui.components.Button;
|
|
import net.minecraft.client.gui.components.MultiLineTextWidget;
|
|
import net.minecraft.client.gui.components.StringWidget;
|
|
import net.minecraft.client.gui.components.Tooltip;
|
|
import net.minecraft.client.gui.layouts.FrameLayout;
|
|
import net.minecraft.client.gui.layouts.LinearLayout;
|
|
import net.minecraft.client.gui.screens.AlertScreen;
|
|
import net.minecraft.client.gui.screens.ConfirmLinkScreen;
|
|
import net.minecraft.client.gui.screens.ConfirmScreen;
|
|
import net.minecraft.client.gui.screens.GenericMessageScreen;
|
|
import net.minecraft.client.gui.screens.Screen;
|
|
import net.minecraft.client.gui.screens.worldselection.EditWorldScreen;
|
|
import net.minecraft.client.gui.screens.worldselection.WorldSelectionList;
|
|
import net.minecraft.nbt.NbtException;
|
|
import net.minecraft.nbt.ReportedNbtException;
|
|
import net.minecraft.network.chat.CommonComponents;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.MutableComponent;
|
|
import net.minecraft.util.CommonLinks;
|
|
import net.minecraft.world.level.storage.LevelStorageSource;
|
|
import org.jspecify.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public class RecoverWorldDataScreen
|
|
extends Screen {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final int SCREEN_SIDE_MARGIN = 25;
|
|
private static final Component TITLE = Component.translatable("recover_world.title").withStyle(ChatFormatting.BOLD);
|
|
private static final Component BUGTRACKER_BUTTON = Component.translatable("recover_world.bug_tracker");
|
|
private static final Component RESTORE_BUTTON = Component.translatable("recover_world.restore");
|
|
private static final Component NO_FALLBACK_TOOLTIP = Component.translatable("recover_world.no_fallback");
|
|
private static final Component DONE_TITLE = Component.translatable("recover_world.done.title");
|
|
private static final Component DONE_SUCCESS = Component.translatable("recover_world.done.success");
|
|
private static final Component DONE_FAILED = Component.translatable("recover_world.done.failed");
|
|
private static final Component NO_ISSUES = Component.translatable("recover_world.issue.none").withStyle(ChatFormatting.GREEN);
|
|
private static final Component MISSING_FILE = Component.translatable("recover_world.issue.missing_file").withStyle(ChatFormatting.RED);
|
|
private final BooleanConsumer callback;
|
|
private final LinearLayout layout = LinearLayout.vertical().spacing(8);
|
|
private final Component message;
|
|
private final MultiLineTextWidget messageWidget;
|
|
private final MultiLineTextWidget issuesWidget;
|
|
private final LevelStorageSource.LevelStorageAccess storageAccess;
|
|
|
|
public RecoverWorldDataScreen(Minecraft minecraft, BooleanConsumer callback, LevelStorageSource.LevelStorageAccess storageAccess) {
|
|
super(TITLE);
|
|
this.callback = callback;
|
|
this.message = Component.translatable("recover_world.message", Component.literal(storageAccess.getLevelId()).withStyle(ChatFormatting.GRAY));
|
|
this.messageWidget = new MultiLineTextWidget(this.message, minecraft.font);
|
|
this.storageAccess = storageAccess;
|
|
Exception levelDatIssues = this.collectIssue(storageAccess, false);
|
|
Exception levelDatOldIssues = this.collectIssue(storageAccess, true);
|
|
MutableComponent issues = Component.empty().append(this.buildInfo(storageAccess, false, levelDatIssues)).append("\n").append(this.buildInfo(storageAccess, true, levelDatOldIssues));
|
|
this.issuesWidget = new MultiLineTextWidget(issues, minecraft.font);
|
|
boolean canRecover = levelDatIssues != null && levelDatOldIssues == null;
|
|
this.layout.defaultCellSetting().alignHorizontallyCenter();
|
|
this.layout.addChild(new StringWidget(this.title, minecraft.font));
|
|
this.layout.addChild(this.messageWidget.setCentered(true));
|
|
this.layout.addChild(this.issuesWidget);
|
|
LinearLayout buttonGrid = LinearLayout.horizontal().spacing(5);
|
|
buttonGrid.addChild(Button.builder(BUGTRACKER_BUTTON, ConfirmLinkScreen.confirmLink((Screen)this, CommonLinks.SNAPSHOT_BUGS_FEEDBACK)).size(120, 20).build());
|
|
buttonGrid.addChild(Button.builder((Component)RecoverWorldDataScreen.RESTORE_BUTTON, (Button.OnPress)(Button.OnPress)LambdaMetafactory.metafactory(null, null, null, (Lnet/minecraft/client/gui/components/Button;)V, lambda$new$0(net.minecraft.client.Minecraft net.minecraft.client.gui.components.Button ), (Lnet/minecraft/client/gui/components/Button;)V)((RecoverWorldDataScreen)this, (Minecraft)minecraft)).size((int)120, (int)20).tooltip((Tooltip)(canRecover ? null : Tooltip.create((Component)RecoverWorldDataScreen.NO_FALLBACK_TOOLTIP))).build()).active = canRecover;
|
|
this.layout.addChild(buttonGrid);
|
|
this.layout.addChild(Button.builder(CommonComponents.GUI_BACK, button -> this.onClose()).size(120, 20).build());
|
|
this.layout.visitWidgets(this::addRenderableWidget);
|
|
}
|
|
|
|
private void attemptRestore(Minecraft minecraft) {
|
|
Exception current = this.collectIssue(this.storageAccess, false);
|
|
Exception old = this.collectIssue(this.storageAccess, true);
|
|
if (current == null || old != null) {
|
|
LOGGER.error("Failed to recover world, files not as expected. level.dat: {}, level.dat_old: {}", (Object)(current != null ? current.getMessage() : "no issues"), (Object)(old != null ? old.getMessage() : "no issues"));
|
|
minecraft.setScreen(new AlertScreen(() -> this.callback.accept(false), DONE_TITLE, DONE_FAILED));
|
|
return;
|
|
}
|
|
minecraft.setScreenAndShow(new GenericMessageScreen(Component.translatable("recover_world.restoring")));
|
|
EditWorldScreen.makeBackupAndShowToast(this.storageAccess);
|
|
if (this.storageAccess.restoreLevelDataFromOld()) {
|
|
minecraft.setScreen(new ConfirmScreen(this.callback, DONE_TITLE, DONE_SUCCESS, CommonComponents.GUI_CONTINUE, CommonComponents.GUI_BACK));
|
|
} else {
|
|
minecraft.setScreen(new AlertScreen(() -> this.callback.accept(false), DONE_TITLE, DONE_FAILED));
|
|
}
|
|
}
|
|
|
|
private Component buildInfo(LevelStorageSource.LevelStorageAccess access, boolean fallback, @Nullable Exception exception) {
|
|
if (fallback && exception instanceof FileNotFoundException) {
|
|
return Component.empty();
|
|
}
|
|
MutableComponent component = Component.empty();
|
|
Instant timeStamp = access.getFileModificationTime(fallback);
|
|
MutableComponent time = timeStamp != null ? Component.literal(WorldSelectionList.DATE_FORMAT.format(ZonedDateTime.ofInstant(timeStamp, ZoneId.systemDefault()))) : Component.translatable("recover_world.state_entry.unknown");
|
|
component.append(Component.translatable("recover_world.state_entry", time.withStyle(ChatFormatting.GRAY)));
|
|
if (exception == null) {
|
|
component.append(NO_ISSUES);
|
|
} else if (exception instanceof FileNotFoundException) {
|
|
component.append(MISSING_FILE);
|
|
} else if (exception instanceof ReportedNbtException) {
|
|
component.append(Component.literal(exception.getCause().toString()).withStyle(ChatFormatting.RED));
|
|
} else {
|
|
component.append(Component.literal(exception.toString()).withStyle(ChatFormatting.RED));
|
|
}
|
|
return component;
|
|
}
|
|
|
|
private @Nullable Exception collectIssue(LevelStorageSource.LevelStorageAccess access, boolean useFallback) {
|
|
try {
|
|
if (!useFallback) {
|
|
access.getSummary(access.getDataTag());
|
|
} else {
|
|
access.getSummary(access.getDataTagFallback());
|
|
}
|
|
}
|
|
catch (IOException | NbtException | ReportedNbtException e) {
|
|
return e;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
protected void init() {
|
|
super.init();
|
|
this.repositionElements();
|
|
}
|
|
|
|
@Override
|
|
protected void repositionElements() {
|
|
this.issuesWidget.setMaxWidth(this.width - 50);
|
|
this.messageWidget.setMaxWidth(this.width - 50);
|
|
this.layout.arrangeElements();
|
|
FrameLayout.centerInRectangle(this.layout, this.getRectangle());
|
|
}
|
|
|
|
@Override
|
|
public Component getNarrationMessage() {
|
|
return CommonComponents.joinForNarration(super.getNarrationMessage(), this.message);
|
|
}
|
|
|
|
@Override
|
|
public void onClose() {
|
|
this.callback.accept(false);
|
|
}
|
|
|
|
private /* synthetic */ void lambda$new$0(Minecraft minecraft, Button button) {
|
|
this.attemptRestore(minecraft);
|
|
}
|
|
}
|
|
|