Add rename/discard options to "Replay Saving" gui (closes #319)

This commit is contained in:
Jonas Herzig
2020-08-28 21:21:25 +02:00
parent ab2b89f838
commit c2d4ac20dc
4 changed files with 190 additions and 18 deletions

2
jGui

Submodule jGui updated: e9387ad003...7713f2985a

View File

@@ -14,6 +14,7 @@ import com.replaymod.replaystudio.replay.ReplayMetaData;
import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.replay.ZipReplayFile;
import com.replaymod.replaystudio.stream.IteratorStream; import com.replaymod.replaystudio.stream.IteratorStream;
import com.replaymod.replaystudio.studio.ReplayStudio; import com.replaymod.replaystudio.studio.ReplayStudio;
import com.replaymod.replaystudio.us.myles.ViaVersion.api.Pair;
import com.replaymod.replaystudio.util.Utils; import com.replaymod.replaystudio.util.Utils;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
@@ -106,9 +107,13 @@ public class MarkerProcessor {
return suffixes; return suffixes;
} }
public static void apply(Path path, Consumer<Float> progress) throws IOException { public static List<Pair<Path, ReplayMetaData>> apply(Path path, Consumer<Float> progress) throws IOException {
if (!hasWork(path)) { if (!hasWork(path)) {
return; ReplayMetaData metaData;
try (ZipReplayFile inputReplayFile = new ZipReplayFile(new ReplayStudio(), path.toFile())) {
metaData = inputReplayFile.getMetaData();
}
return Collections.singletonList(new Pair<>(path, metaData));
} }
String replayName = FilenameUtils.getBaseName(path.getFileName().toString()); String replayName = FilenameUtils.getBaseName(path.getFileName().toString());
@@ -119,6 +124,8 @@ public class MarkerProcessor {
SquashFilter squashFilter = new SquashFilter(); SquashFilter squashFilter = new SquashFilter();
squashFilter.init(studio, null); squashFilter.init(studio, null);
List<Pair<Path, ReplayMetaData>> outputPaths = new ArrayList<>();
Path inputPath = path.resolveSibling("raw").resolve(path.getFileName()); Path inputPath = path.resolveSibling("raw").resolve(path.getFileName());
Files.createDirectories(inputPath.getParent()); Files.createDirectories(inputPath.getParent());
Files.move(path, inputPath); Files.move(path, inputPath);
@@ -139,7 +146,8 @@ public class MarkerProcessor {
Marker nextMarker = markerIterator.next(); Marker nextMarker = markerIterator.next();
while (nextPacket != null && outputFileSuffixes.hasNext()) { while (nextPacket != null && outputFileSuffixes.hasNext()) {
File outputFile = path.resolveSibling(replayName + outputFileSuffixes.next() + ".mcpr").toFile(); Path outputPath = path.resolveSibling(replayName + outputFileSuffixes.next() + ".mcpr");
File outputFile = outputPath.toFile();
try (ZipReplayFile outputReplayFile = new ZipReplayFile(studio, null, outputFile)) { try (ZipReplayFile outputReplayFile = new ZipReplayFile(studio, null, outputFile)) {
long duration = 0; long duration = 0;
Set<Marker> outputMarkers = new HashSet<>(); Set<Marker> outputMarkers = new HashSet<>();
@@ -237,6 +245,8 @@ public class MarkerProcessor {
} }
outputReplayFile.save(); outputReplayFile.save();
outputPaths.add(new Pair(outputPath, metaData));
} }
} }
@@ -245,5 +255,7 @@ public class MarkerProcessor {
cutFilter.release(); cutFilter.release();
} }
} }
return outputPaths;
} }
} }

View File

@@ -0,0 +1,161 @@
package com.replaymod.recording.gui;
import com.replaymod.core.ReplayMod;
import com.replaymod.core.utils.Utils;
import com.replaymod.replay.gui.screen.GuiReplayViewer;
import com.replaymod.replaystudio.replay.ReplayMetaData;
import com.replaymod.replaystudio.us.myles.ViaVersion.api.Pair;
import de.johni0702.minecraft.gui.container.GuiContainer;
import de.johni0702.minecraft.gui.container.GuiPanel;
import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
import de.johni0702.minecraft.gui.element.GuiButton;
import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.GuiTextField;
import de.johni0702.minecraft.gui.element.GuiTooltip;
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
import de.johni0702.minecraft.gui.function.Focusable;
import de.johni0702.minecraft.gui.layout.CustomLayout;
import de.johni0702.minecraft.gui.layout.HorizontalLayout;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.utils.Colors;
import de.johni0702.minecraft.gui.utils.lwjgl.Dimension;
import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.crash.CrashReport;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import static com.replaymod.core.versions.MCVer.getMinecraft;
import static de.johni0702.minecraft.gui.utils.Utils.link;
public class GuiSavingReplay {
private static final MinecraftClient mc = getMinecraft();
private static final Logger logger = LogManager.getLogger();
private final GuiLabel label = new GuiLabel()
.setI18nText("replaymod.gui.replaysaving.title")
.setColor(Colors.BLACK);
private final GuiProgressBar progressBar = new GuiProgressBar()
.setHeight(14);
private final GuiPanel panel = new GuiPanel()
.setLayout(new VerticalLayout().setSpacing(2))
.addElements(new VerticalLayout.Data(0.5), label, progressBar);
private final ReplayMod core;
private final List<Runnable> apply = new ArrayList<>();
public GuiSavingReplay(ReplayMod core) {
this.core = core;
}
public void open() {
core.getBackgroundProcesses().addProcess(panel);
}
public void close() {
core.getBackgroundProcesses().removeProcess(panel);
}
public GuiProgressBar getProgressBar() {
return progressBar;
}
public void presentRenameDialog(List<Pair<Path, ReplayMetaData>> outputPaths) {
panel.removeElement(progressBar);
link(outputPaths.stream().map(it -> addOutput(it.getKey(), it.getValue())).toArray(Focusable[]::new));
GuiButton applyButton = new GuiButton()
.setSize(150, 20)
.setI18nLabel("replaymod.gui.done")
.onClick(() -> {
apply.forEach(Runnable::run);
close();
});
panel.addElements(new VerticalLayout.Data(0.5), applyButton);
}
private GuiTextField addOutput(Path path, ReplayMetaData metaData) {
String originalName = Utils.fileNameToReplayName(path.getFileName().toString());
GuiTextField textField = new GuiTextField()
.setSize(130, 20)
.setText(originalName)
.setI18nHint("replaymod.gui.delete")
.setTextColorDisabled(Colors.RED)
.setTooltip(createTooltip(path, metaData));
GuiButton clearButton = new GuiButton()
.setSize(20, 20)
.setLabel("X")
.setTooltip(new GuiTooltip().setI18nText("replaymod.gui.delete"))
.onClick(() -> textField.setText(""));
GuiPanel row = new GuiPanel()
.setLayout(new HorizontalLayout())
.addElements(null, textField, clearButton);
panel.addElements(new VerticalLayout.Data(0.5), row);
apply.add(() -> {
String newName = textField.getText();
if (newName.equals(originalName)) {
return;
}
applyOutput(path, newName);
});
return textField;
}
private GuiPanel createTooltip(Path path, ReplayMetaData metaData) {
GuiTooltip tooltip = new GuiTooltip();
GuiReplayViewer.GuiReplayEntry entry = new GuiReplayViewer.GuiReplayEntry(path.toFile(), metaData, null);
return new GuiPanel().setLayout(new CustomLayout<GuiPanel>() {
@Override
protected void layout(GuiPanel container, int width, int height) {
pos(entry, 4, 4);
size(entry, width - 8, height - 8);
size(tooltip, width, height);
}
@Override
public ReadableDimension calcMinSize(GuiContainer<?> container) {
ReadableDimension size = entry.calcMinSize();
return new Dimension(size.getWidth() + 8, size.getHeight() + 8);
}
}).addElements(null, tooltip, entry);
}
private void applyOutput(Path path, String newName) {
if (newName.isEmpty()) {
try {
Files.delete(path);
} catch (IOException e) {
logger.error("Deleting replay file:", e);
CrashReport crashReport = CrashReport.create(e, "Deleting replay file");
core.runLater(() -> Utils.error(logger, VanillaGuiScreen.setup(mc.currentScreen), crashReport, () -> {}));
}
return;
}
Path newPath = path.resolveSibling(Utils.replayNameToFileName(newName));
if (Files.exists(newPath)) {
return;
}
try {
Files.move(path, newPath);
} catch (IOException e) {
logger.error("Renaming replay file:", e);
CrashReport crashReport = CrashReport.create(e, "Renaming replay file");
core.runLater(() -> Utils.error(logger, VanillaGuiScreen.setup(mc.currentScreen), crashReport, () -> {}));
}
}
}

View File

@@ -11,6 +11,7 @@ import com.replaymod.core.versions.MCVer;
import com.replaymod.editor.gui.MarkerProcessor; import com.replaymod.editor.gui.MarkerProcessor;
import com.replaymod.recording.ReplayModRecording; import com.replaymod.recording.ReplayModRecording;
import com.replaymod.recording.Setting; import com.replaymod.recording.Setting;
import com.replaymod.recording.gui.GuiSavingReplay;
import com.replaymod.recording.handler.ConnectionEventHandler; import com.replaymod.recording.handler.ConnectionEventHandler;
import com.replaymod.recording.mixin.SPacketSpawnMobAccessor; import com.replaymod.recording.mixin.SPacketSpawnMobAccessor;
import com.replaymod.recording.mixin.SPacketSpawnPlayerAccessor; import com.replaymod.recording.mixin.SPacketSpawnPlayerAccessor;
@@ -19,12 +20,8 @@ import com.replaymod.replaystudio.data.Marker;
import com.replaymod.replaystudio.io.ReplayOutputStream; import com.replaymod.replaystudio.io.ReplayOutputStream;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ReplayMetaData;
import de.johni0702.minecraft.gui.container.GuiPanel; import com.replaymod.replaystudio.us.myles.ViaVersion.api.Pair;
import de.johni0702.minecraft.gui.container.VanillaGuiScreen; import de.johni0702.minecraft.gui.container.VanillaGuiScreen;
import de.johni0702.minecraft.gui.element.GuiLabel;
import de.johni0702.minecraft.gui.element.advanced.GuiProgressBar;
import de.johni0702.minecraft.gui.layout.VerticalLayout;
import de.johni0702.minecraft.gui.utils.Colors;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
@@ -70,7 +67,9 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -248,13 +247,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
}); });
GuiLabel label = new GuiLabel().setI18nText("replaymod.gui.replaysaving.title").setColor(Colors.BLACK); GuiSavingReplay guiSavingReplay = new GuiSavingReplay(core);
GuiProgressBar progressBar = new GuiProgressBar().setHeight(14);
GuiPanel savingProcess = new GuiPanel()
.setLayout(new VerticalLayout())
.addElements(new VerticalLayout.Data(0.5), label, progressBar);
new Thread(() -> { new Thread(() -> {
core.runLater(() -> core.getBackgroundProcesses().addProcess(savingProcess)); core.runLater(guiSavingReplay::open);
saveService.shutdown(); saveService.shutdown();
try { try {
@@ -268,22 +263,26 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
logger.error("Failed to close packet output stream:", e); logger.error("Failed to close packet output stream:", e);
} }
List<Pair<Path, ReplayMetaData>> outputPaths;
synchronized (replayFile) { synchronized (replayFile) {
try { try {
replayFile.save(); replayFile.save();
replayFile.close(); replayFile.close();
if (core.getSettingsRegistry().get(Setting.AUTO_POST_PROCESS) && !ReplayMod.isMinimalMode()) { if (core.getSettingsRegistry().get(Setting.AUTO_POST_PROCESS) && !ReplayMod.isMinimalMode()) {
MarkerProcessor.apply(outputPath, progressBar::setProgress); outputPaths = MarkerProcessor.apply(outputPath, guiSavingReplay.getProgressBar()::setProgress);
} else {
outputPaths = Collections.singletonList(new Pair<>(outputPath, metaData));
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("Saving replay file:", e); logger.error("Saving replay file:", e);
CrashReport crashReport = CrashReport.create(e, "Saving replay file"); CrashReport crashReport = CrashReport.create(e, "Saving replay file");
core.runLater(() -> Utils.error(logger, VanillaGuiScreen.setup(mc.currentScreen), crashReport, () -> {})); core.runLater(() -> Utils.error(logger, VanillaGuiScreen.setup(mc.currentScreen), crashReport, guiSavingReplay::close));
return;
} }
} }
core.runLater(() -> core.getBackgroundProcesses().removeProcess(savingProcess)); core.runLater(() -> guiSavingReplay.presentRenameDialog(outputPaths));
}).start(); }).start();
} }