Run recovery in background with progress indicator (closes #326)
This commit is contained in:
@@ -403,7 +403,7 @@ public class ReplayMod implements
|
|||||||
for (File file : files) {
|
for (File file : files) {
|
||||||
if (file.isDirectory() && file.getName().endsWith(".mcpr.tmp")) {
|
if (file.isDirectory() && file.getName().endsWith(".mcpr.tmp")) {
|
||||||
File origFile = new File(file.getParentFile(), Files.getNameWithoutExtension(file.getName()));
|
File origFile = new File(file.getParentFile(), Files.getNameWithoutExtension(file.getName()));
|
||||||
new RestoreReplayGui(GuiScreen.wrap(mc.currentScreen), origFile).display();
|
new RestoreReplayGui(this, GuiScreen.wrap(mc.currentScreen), origFile).display();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.replaymod.core.gui;
|
|||||||
|
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.core.utils.Utils;
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
import com.replaymod.replaystudio.io.ReplayInputStream;
|
import com.replaymod.replaystudio.io.ReplayInputStream;
|
||||||
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
||||||
@@ -12,22 +14,30 @@ import com.replaymod.replaystudio.studio.ReplayStudio;
|
|||||||
import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
|
import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
|
||||||
import de.johni0702.minecraft.gui.container.GuiPanel;
|
import de.johni0702.minecraft.gui.container.GuiPanel;
|
||||||
import de.johni0702.minecraft.gui.container.GuiScreen;
|
import de.johni0702.minecraft.gui.container.GuiScreen;
|
||||||
|
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
|
||||||
import de.johni0702.minecraft.gui.element.GuiButton;
|
import de.johni0702.minecraft.gui.element.GuiButton;
|
||||||
import de.johni0702.minecraft.gui.element.GuiLabel;
|
import de.johni0702.minecraft.gui.element.GuiLabel;
|
||||||
|
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
|
||||||
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
import de.johni0702.minecraft.gui.layout.CustomLayout;
|
||||||
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
|
||||||
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
import de.johni0702.minecraft.gui.layout.VerticalLayout;
|
||||||
|
import de.johni0702.minecraft.gui.utils.Colors;
|
||||||
|
import net.minecraft.util.crash.CrashReport;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static com.replaymod.replaystudio.util.Utils.readInt;
|
import static com.replaymod.replaystudio.util.Utils.readInt;
|
||||||
import static com.replaymod.replaystudio.util.Utils.writeInt;
|
import static com.replaymod.replaystudio.util.Utils.writeInt;
|
||||||
|
|
||||||
public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
|
public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
|
||||||
|
private static Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
public final GuiScreen parent;
|
public final GuiScreen parent;
|
||||||
public final File file;
|
public final File file;
|
||||||
@@ -37,8 +47,10 @@ public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
|
|||||||
textPanel, buttonPanel).setLayout(new VerticalLayout().setSpacing(20));
|
textPanel, buttonPanel).setLayout(new VerticalLayout().setSpacing(20));
|
||||||
public final GuiButton yesButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.yes");
|
public final GuiButton yesButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.yes");
|
||||||
public final GuiButton noButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.no");
|
public final GuiButton noButton = new GuiButton(buttonPanel).setSize(150, 20).setI18nLabel("gui.no");
|
||||||
|
private final ReplayMod core;
|
||||||
|
|
||||||
public RestoreReplayGui(GuiScreen parent, File file) {
|
public RestoreReplayGui(ReplayMod core, GuiScreen parent, File file) {
|
||||||
|
this.core = core;
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
|
|
||||||
@@ -47,12 +59,63 @@ public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
|
|||||||
new GuiLabel().setI18nText("replaymod.gui.restorereplay2", Files.getNameWithoutExtension(file.getName())),
|
new GuiLabel().setI18nText("replaymod.gui.restorereplay2", Files.getNameWithoutExtension(file.getName())),
|
||||||
new GuiLabel().setI18nText("replaymod.gui.restorereplay3"));
|
new GuiLabel().setI18nText("replaymod.gui.restorereplay3"));
|
||||||
yesButton.onClick(() -> {
|
yesButton.onClick(() -> {
|
||||||
|
recoverInBackground();
|
||||||
|
parent.display();
|
||||||
|
});
|
||||||
|
noButton.onClick(() -> {
|
||||||
try {
|
try {
|
||||||
|
File tmp = new File(file.getParentFile(), file.getName() + ".tmp");
|
||||||
|
File deleted = new File(file.getParentFile(), file.getName() + ".del");
|
||||||
|
if (deleted.exists()) {
|
||||||
|
FileUtils.deleteDirectory(deleted);
|
||||||
|
}
|
||||||
|
Files.move(tmp, deleted);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
parent.display();
|
||||||
|
});
|
||||||
|
|
||||||
|
setLayout(new CustomLayout<RestoreReplayGui>() {
|
||||||
|
@Override
|
||||||
|
protected void layout(RestoreReplayGui container, int width, int height) {
|
||||||
|
pos(contentPanel, width / 2 - width(contentPanel) / 2, height / 2 - height(contentPanel) / 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RestoreReplayGui getThis() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void recoverInBackground() {
|
||||||
|
GuiLabel label = new GuiLabel().setI18nText("replaymod.gui.replaysaving.title").setColor(Colors.BLACK);
|
||||||
|
GuiProgressBar progressBar = new GuiProgressBar().setHeight(14);
|
||||||
|
GuiPanel savingProcess = new GuiPanel()
|
||||||
|
.setLayout(new VerticalLayout())
|
||||||
|
.addElements(new VerticalLayout.Data(0.5), label, progressBar);
|
||||||
|
new Thread(() -> {
|
||||||
|
core.runLater(() -> core.getBackgroundProcesses().addProcess(savingProcess));
|
||||||
|
try {
|
||||||
|
tryRecover(progressBar::setProgress);
|
||||||
|
} catch (IOException e) {
|
||||||
|
LOGGER.error("Recovering replay file:", e);
|
||||||
|
CrashReport crashReport = CrashReport.create(e, "Recovering replay file");
|
||||||
|
core.runLater(() -> Utils.error(LOGGER, VanillaGuiScreen.setup(getMinecraft().currentScreen), crashReport, () -> {}));
|
||||||
|
} finally {
|
||||||
|
core.runLater(() -> core.getBackgroundProcesses().removeProcess(savingProcess));
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryRecover(Consumer<Float> progress) throws IOException {
|
||||||
ReplayStudio studio = new ReplayStudio();
|
ReplayStudio studio = new ReplayStudio();
|
||||||
ReplayFile replayFile = new ZipReplayFile(studio, null, file);
|
ReplayFile replayFile = new ZipReplayFile(studio, null, file);
|
||||||
// Commit all not-yet-committed files into the main zip file.
|
// Commit all not-yet-committed files into the main zip file.
|
||||||
// If we don't do this, then re-writing packet data below can actually overwrite uncommitted packet data!
|
// If we don't do this, then re-writing packet data below can actually overwrite uncommitted packet data!
|
||||||
replayFile.save();
|
replayFile.save();
|
||||||
|
progress.accept(0.4f);
|
||||||
ReplayMetaData metaData = replayFile.getMetaData();
|
ReplayMetaData metaData = replayFile.getMetaData();
|
||||||
if (metaData != null && metaData.getDuration() == 0) {
|
if (metaData != null && metaData.getDuration() == 0) {
|
||||||
// Try to restore replay duration
|
// Try to restore replay duration
|
||||||
@@ -88,37 +151,10 @@ public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
|
|||||||
out.write(json.getBytes());
|
out.write(json.getBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
progress.accept(0.6f);
|
||||||
replayFile.save();
|
replayFile.save();
|
||||||
|
progress.accept(0.9f);
|
||||||
replayFile.close();
|
replayFile.close();
|
||||||
} catch (IOException e) {
|
progress.accept(1f);
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
parent.display();
|
|
||||||
});
|
|
||||||
noButton.onClick(() -> {
|
|
||||||
try {
|
|
||||||
File tmp = new File(file.getParentFile(), file.getName() + ".tmp");
|
|
||||||
File deleted = new File(file.getParentFile(), file.getName() + ".del");
|
|
||||||
if (deleted.exists()) {
|
|
||||||
FileUtils.deleteDirectory(deleted);
|
|
||||||
}
|
|
||||||
Files.move(tmp, deleted);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
parent.display();
|
|
||||||
});
|
|
||||||
|
|
||||||
setLayout(new CustomLayout<RestoreReplayGui>() {
|
|
||||||
@Override
|
|
||||||
protected void layout(RestoreReplayGui container, int width, int height) {
|
|
||||||
pos(contentPanel, width / 2 - width(contentPanel) / 2, height / 2 - height(contentPanel) / 2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected RestoreReplayGui getThis() {
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user