Improve MarkerProcessor output generation (fixes multiple issues)
In particular: - No longer generate any replays when auto-recording is off and recording is never enabled from the ingame menu (fixes #138) - Do not generate an additional empty replay file when recording was stopped in ingame menu (fixes #147) - only do squash if there are further output replays (fixes #142) - Use the input file name as output file name even if there was a split (as long as it's the only output file, e.g. because recording was never un-paused after the split)
This commit is contained in:
@@ -9,6 +9,7 @@ import com.replaymod.replaystudio.filter.StreamFilter;
|
|||||||
import com.replaymod.replaystudio.io.ReplayInputStream;
|
import com.replaymod.replaystudio.io.ReplayInputStream;
|
||||||
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
import com.replaymod.replaystudio.io.ReplayOutputStream;
|
||||||
import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
|
import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
|
||||||
|
import com.replaymod.replaystudio.replay.ReplayFile;
|
||||||
import com.replaymod.replaystudio.replay.ReplayMetaData;
|
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;
|
||||||
@@ -16,12 +17,14 @@ import com.replaymod.replaystudio.studio.ReplayStudio;
|
|||||||
import com.replaymod.replaystudio.util.Utils;
|
import com.replaymod.replaystudio.util.Utils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -52,6 +55,57 @@ public class MarkerProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private enum OutputState {
|
||||||
|
/** A new output file has begun but not data has been written yet. */
|
||||||
|
NotYetWriting,
|
||||||
|
/** Currently writing data to the active output file. */
|
||||||
|
Writing,
|
||||||
|
/** Currently not writing data. */
|
||||||
|
Paused,
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<String> getOutputSuffixes(ReplayFile inputReplayFile) throws IOException {
|
||||||
|
List<Marker> markers = inputReplayFile.getMarkers().or(HashSet::new)
|
||||||
|
.stream().sorted(Comparator.comparing(Marker::getTime)).collect(Collectors.toList());
|
||||||
|
int nextSuffix = 0;
|
||||||
|
List<String> suffixes = new ArrayList<>();
|
||||||
|
OutputState state = OutputState.Writing;
|
||||||
|
for (Marker marker : markers) {
|
||||||
|
if (MARKER_NAME_START_CUT.equals(marker.getName())) {
|
||||||
|
if (marker.getTime() == 0) {
|
||||||
|
// Special case: Automatic recording has been disabled
|
||||||
|
state = OutputState.NotYetWriting;
|
||||||
|
} else {
|
||||||
|
state = OutputState.Paused;
|
||||||
|
}
|
||||||
|
} else if (MARKER_NAME_END_CUT.equals(marker.getName())) {
|
||||||
|
state = OutputState.Writing;
|
||||||
|
} else if (MARKER_NAME_SPLIT.equals(marker.getName())) {
|
||||||
|
switch (state) {
|
||||||
|
case NotYetWriting:
|
||||||
|
break;
|
||||||
|
case Writing:
|
||||||
|
suffixes.add("_" + nextSuffix++);
|
||||||
|
state = OutputState.Writing;
|
||||||
|
break;
|
||||||
|
case Paused:
|
||||||
|
suffixes.add("_" + nextSuffix++);
|
||||||
|
state = OutputState.NotYetWriting;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state != OutputState.NotYetWriting) {
|
||||||
|
suffixes.add("_" + nextSuffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suffixes.size() == 1) {
|
||||||
|
// If there's only one output, it can keep the name of the input
|
||||||
|
return Collections.singletonList("");
|
||||||
|
}
|
||||||
|
return suffixes;
|
||||||
|
}
|
||||||
|
|
||||||
public static void apply(Path path, Consumer<Float> progress) throws IOException {
|
public static void apply(Path path, Consumer<Float> progress) throws IOException {
|
||||||
if (!hasWork(path)) {
|
if (!hasWork(path)) {
|
||||||
return;
|
return;
|
||||||
@@ -73,6 +127,7 @@ public class MarkerProcessor {
|
|||||||
List<Marker> markers = inputReplayFile.getMarkers().or(HashSet::new)
|
List<Marker> markers = inputReplayFile.getMarkers().or(HashSet::new)
|
||||||
.stream().sorted(Comparator.comparing(Marker::getTime)).collect(Collectors.toList());
|
.stream().sorted(Comparator.comparing(Marker::getTime)).collect(Collectors.toList());
|
||||||
Iterator<Marker> markerIterator = markers.iterator();
|
Iterator<Marker> markerIterator = markers.iterator();
|
||||||
|
Iterator<String> outputFileSuffixes = getOutputSuffixes(inputReplayFile).iterator();
|
||||||
boolean anySplit = markers.stream().anyMatch(m -> MARKER_NAME_SPLIT.equals(m.getName()));
|
boolean anySplit = markers.stream().anyMatch(m -> MARKER_NAME_SPLIT.equals(m.getName()));
|
||||||
|
|
||||||
int inputDuration = inputReplayFile.getMetaData().getDuration();
|
int inputDuration = inputReplayFile.getMetaData().getDuration();
|
||||||
@@ -83,9 +138,9 @@ public class MarkerProcessor {
|
|||||||
PacketData nextPacket = replayInputStream.readPacket();
|
PacketData nextPacket = replayInputStream.readPacket();
|
||||||
Marker nextMarker = markerIterator.next();
|
Marker nextMarker = markerIterator.next();
|
||||||
|
|
||||||
while (nextPacket != null) {
|
while (nextPacket != null && outputFileSuffixes.hasNext()) {
|
||||||
try (ZipReplayFile outputReplayFile = new ZipReplayFile(studio, null,
|
File outputFile = path.resolveSibling(replayName + outputFileSuffixes.next() + ".mcpr").toFile();
|
||||||
(anySplit ? path.resolveSibling(replayName + "_" + splitCounter + ".mcpr") : path).toFile())) {
|
try (ZipReplayFile outputReplayFile = new ZipReplayFile(studio, null, outputFile)) {
|
||||||
long duration = 0;
|
long duration = 0;
|
||||||
Set<Marker> outputMarkers = new HashSet<>();
|
Set<Marker> outputMarkers = new HashSet<>();
|
||||||
ReplayMetaData metaData = inputReplayFile.getMetaData();
|
ReplayMetaData metaData = inputReplayFile.getMetaData();
|
||||||
@@ -105,6 +160,7 @@ public class MarkerProcessor {
|
|||||||
replayOutputStream.write(0, packet.getPacket());
|
replayOutputStream.write(0, packet.getPacket());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
boolean hasFurtherOutputs = outputFileSuffixes.hasNext();
|
||||||
|
|
||||||
while (nextPacket != null) {
|
while (nextPacket != null) {
|
||||||
if (nextMarker != null && nextPacket.getTime() > nextMarker.getTime()) {
|
if (nextMarker != null && nextPacket.getTime() > nextMarker.getTime()) {
|
||||||
@@ -141,7 +197,9 @@ public class MarkerProcessor {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasFurtherOutputs) {
|
||||||
squashFilter.onPacket(null, nextPacket);
|
squashFilter.onPacket(null, nextPacket);
|
||||||
|
}
|
||||||
if (cutFilter != null) {
|
if (cutFilter != null) {
|
||||||
cutFilter.onPacket(null, nextPacket);
|
cutFilter.onPacket(null, nextPacket);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user