Add rename/discard options to "Replay Saving" gui (closes #319)
This commit is contained in:
2
jGui
2
jGui
Submodule jGui updated: e9387ad003...7713f2985a
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
161
src/main/java/com/replaymod/recording/gui/GuiSavingReplay.java
Normal file
161
src/main/java/com/replaymod/recording/gui/GuiSavingReplay.java
Normal 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, () -> {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user