Skip to content

Commit e484551

Browse files
committed
Fix ck2 compressed save game corruption on write
1 parent 852a66d commit e484551

File tree

5 files changed

+33
-24
lines changed

5 files changed

+33
-24
lines changed

canonical_version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.13.7
1+
2.13.8

pdxu-io/src/main/java/com/crschnick/pdxu/io/parser/TextFormatParser.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,12 @@ public final synchronized ArrayNode parse(Path file) throws IOException, ParseEx
115115
return parse(file.getFileName().toString(), Files.readAllBytes(file), 0, false);
116116
}
117117

118-
public final synchronized ArrayNode parse(String name, Path file, boolean strict) throws IOException, ParseException {
119-
return parse(name, Files.readAllBytes(file), 0, strict);
118+
public final synchronized ArrayNode parse(String displayName, Path file, boolean strict) throws IOException, ParseException {
119+
return parse(displayName, Files.readAllBytes(file), 0, strict);
120120
}
121121

122-
public final synchronized ArrayNode parse(String name, byte[] input, int start) throws ParseException {
123-
return parse(name, input, start, false);
122+
public final synchronized ArrayNode parse(String displayName, byte[] input, int start) throws ParseException {
123+
return parse(displayName, input, start, false);
124124
}
125125

126126
public final synchronized ArrayNode parse(String name, byte[] input, int start, boolean strict) throws ParseException {

pdxu-io/src/main/java/com/crschnick/pdxu/io/savegame/SavegameStructure.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void writeData(OutputStream out, ArrayNode node) throws IOException {
6363
"CK2txt".getBytes(),
6464
SavegameType.CK2,
6565
Set.of(new ZipSavegameStructure.SavegamePart("meta", "meta"),
66-
new ZipSavegameStructure.SavegamePart("gamestate", "*"))) {
66+
new ZipSavegameStructure.SavegamePart("*", "gamestate"))) {
6767

6868
@Override
6969
public void writeData(OutputStream out, ArrayNode node) throws IOException {

pdxu-io/src/main/java/com/crschnick/pdxu/io/savegame/ZipSavegameStructure.java

+26-17
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
import java.nio.file.FileSystems;
99
import java.nio.file.Files;
1010
import java.nio.file.Path;
11-
import java.util.Arrays;
12-
import java.util.LinkedHashMap;
13-
import java.util.Map;
14-
import java.util.Set;
11+
import java.util.*;
1512
import java.util.zip.ZipEntry;
1613
import java.util.zip.ZipInputStream;
1714

@@ -34,32 +31,32 @@ public static byte[] getFirstHeader(byte[] input, int maxLength) {
3431
private final Set<SavegamePart> parts;
3532
private final String[] ignored;
3633

37-
public ZipSavegameStructure(byte[] header,SavegameType type, Set<SavegamePart> parts, String... ignored) {
34+
public ZipSavegameStructure(byte[] header,SavegameType type, Set<SavegamePart> parts, String... ignoredFiles) {
3835
this.header = header;
3936
this.type = type;
4037
this.parts = parts;
41-
this.ignored = ignored;
38+
this.ignored = ignoredFiles;
4239
}
4340

4441
protected SavegameParseResult parseInput(byte[] input, int offset) {
4542
var wildcard = parts.stream()
46-
.filter(p -> p.identifier().equals("*"))
43+
.filter(p -> p.fileName().equals("*"))
4744
.findAny();
4845

4946
try {
5047
try (var zipIn = new ZipInputStream(new ByteArrayInputStream(input, offset, input.length - offset))) {
5148
Map<String, ArrayNode> nodes = new LinkedHashMap<>();
5249
ZipEntry entry;
5350
while ((entry = zipIn.getNextEntry()) != null) {
54-
ZipEntry finalEntry = entry;
51+
ZipEntry finalZipEntry = entry;
5552

5653
// Skip ignored entries
57-
if (Arrays.stream(ignored).anyMatch(s -> s.equals(finalEntry.getName()))) {
54+
if (Arrays.stream(ignored).anyMatch(s -> s.equals(finalZipEntry.getName()))) {
5855
continue;
5956
}
6057

6158
var part = parts.stream()
62-
.filter(p -> p.identifier().equals(finalEntry.getName()))
59+
.filter(p -> p.fileName().equals(finalZipEntry.getName()))
6360
.findAny().or(() -> wildcard);
6461

6562
// Ignore unknown entry
@@ -72,16 +69,16 @@ protected SavegameParseResult parseInput(byte[] input, int offset) {
7269
return new SavegameParseResult.Invalid("File " + part.get().identifier() + " has an invalid header");
7370
}
7471

75-
var node = type.getParser().parse(part.get().name, bytes, header != null ? header.length + 1 : 0);
72+
var node = type.getParser().parse(part.get().identifier(), bytes, header != null ? header.length + 1 : 0);
7673
if (node.size() == 0) {
77-
return new SavegameParseResult.Invalid("File " + entry.getName() + " is empty");
74+
return new SavegameParseResult.Invalid("File " + part.get().identifier() + " is empty");
7875
}
7976

80-
nodes.put(part.get().name(), node);
77+
nodes.put(part.get().identifier(), node);
8178
}
8279

8380
var missingParts = parts.stream()
84-
.map(SavegamePart::name)
81+
.map(SavegamePart::identifier)
8582
.filter(s -> !nodes.containsKey(s))
8683
.toList();
8784
if (missingParts.size() > 0) {
@@ -98,15 +95,27 @@ protected SavegameParseResult parseInput(byte[] input, int offset) {
9895
@Override
9996
public void write(Path out, SavegameContent content) throws IOException {
10097
try (var fs = FileSystems.newFileSystem(out, Map.of("create", true))) {
98+
Optional<SavegamePart> wildcardPart;
99+
try (var list = Files.list(fs.getPath("/"))) {
100+
wildcardPart = list.map(path -> path.getFileName().toString()).filter(p -> content.entrySet().stream().noneMatch(e -> p.equals(e.getKey())))
101+
.map(s -> new SavegamePart(s, "gamestate"))
102+
.findAny();
103+
}
104+
101105
for (var e : content.entrySet()) {
102106
var usedPart = parts.stream()
103-
.filter(part -> part.name().equals(e.getKey()))
107+
.filter(part -> part.fileName().equals(e.getKey()))
104108
.findAny();
109+
110+
if (usedPart.isEmpty() && wildcardPart.isPresent() && wildcardPart.get().identifier().equals(e.getKey())) {
111+
usedPart = wildcardPart;
112+
}
113+
105114
if (usedPart.isEmpty()) {
106115
continue;
107116
}
108117

109-
var path = fs.getPath(usedPart.get().identifier());
118+
var path = fs.getPath(usedPart.get().fileName());
110119
try (var partOut = Files.newOutputStream(path)) {
111120
if (header != null) {
112121
partOut.write(header);
@@ -128,6 +137,6 @@ public SavegameType getType() {
128137
return type;
129138
}
130139

131-
public record SavegamePart(String name, String identifier) {
140+
public record SavegamePart(String fileName, String identifier) {
132141
}
133142
}

version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.13.7
1+
2.13.8-SNAPSHOT

0 commit comments

Comments
 (0)