8
8
import java .nio .file .FileSystems ;
9
9
import java .nio .file .Files ;
10
10
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 .*;
15
12
import java .util .zip .ZipEntry ;
16
13
import java .util .zip .ZipInputStream ;
17
14
@@ -34,32 +31,32 @@ public static byte[] getFirstHeader(byte[] input, int maxLength) {
34
31
private final Set <SavegamePart > parts ;
35
32
private final String [] ignored ;
36
33
37
- public ZipSavegameStructure (byte [] header ,SavegameType type , Set <SavegamePart > parts , String ... ignored ) {
34
+ public ZipSavegameStructure (byte [] header ,SavegameType type , Set <SavegamePart > parts , String ... ignoredFiles ) {
38
35
this .header = header ;
39
36
this .type = type ;
40
37
this .parts = parts ;
41
- this .ignored = ignored ;
38
+ this .ignored = ignoredFiles ;
42
39
}
43
40
44
41
protected SavegameParseResult parseInput (byte [] input , int offset ) {
45
42
var wildcard = parts .stream ()
46
- .filter (p -> p .identifier ().equals ("*" ))
43
+ .filter (p -> p .fileName ().equals ("*" ))
47
44
.findAny ();
48
45
49
46
try {
50
47
try (var zipIn = new ZipInputStream (new ByteArrayInputStream (input , offset , input .length - offset ))) {
51
48
Map <String , ArrayNode > nodes = new LinkedHashMap <>();
52
49
ZipEntry entry ;
53
50
while ((entry = zipIn .getNextEntry ()) != null ) {
54
- ZipEntry finalEntry = entry ;
51
+ ZipEntry finalZipEntry = entry ;
55
52
56
53
// 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 ()))) {
58
55
continue ;
59
56
}
60
57
61
58
var part = parts .stream ()
62
- .filter (p -> p .identifier ().equals (finalEntry .getName ()))
59
+ .filter (p -> p .fileName ().equals (finalZipEntry .getName ()))
63
60
.findAny ().or (() -> wildcard );
64
61
65
62
// Ignore unknown entry
@@ -72,16 +69,16 @@ protected SavegameParseResult parseInput(byte[] input, int offset) {
72
69
return new SavegameParseResult .Invalid ("File " + part .get ().identifier () + " has an invalid header" );
73
70
}
74
71
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 );
76
73
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" );
78
75
}
79
76
80
- nodes .put (part .get ().name (), node );
77
+ nodes .put (part .get ().identifier (), node );
81
78
}
82
79
83
80
var missingParts = parts .stream ()
84
- .map (SavegamePart ::name )
81
+ .map (SavegamePart ::identifier )
85
82
.filter (s -> !nodes .containsKey (s ))
86
83
.toList ();
87
84
if (missingParts .size () > 0 ) {
@@ -98,15 +95,27 @@ protected SavegameParseResult parseInput(byte[] input, int offset) {
98
95
@ Override
99
96
public void write (Path out , SavegameContent content ) throws IOException {
100
97
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
+
101
105
for (var e : content .entrySet ()) {
102
106
var usedPart = parts .stream ()
103
- .filter (part -> part .name ().equals (e .getKey ()))
107
+ .filter (part -> part .fileName ().equals (e .getKey ()))
104
108
.findAny ();
109
+
110
+ if (usedPart .isEmpty () && wildcardPart .isPresent () && wildcardPart .get ().identifier ().equals (e .getKey ())) {
111
+ usedPart = wildcardPart ;
112
+ }
113
+
105
114
if (usedPart .isEmpty ()) {
106
115
continue ;
107
116
}
108
117
109
- var path = fs .getPath (usedPart .get ().identifier ());
118
+ var path = fs .getPath (usedPart .get ().fileName ());
110
119
try (var partOut = Files .newOutputStream (path )) {
111
120
if (header != null ) {
112
121
partOut .write (header );
@@ -128,6 +137,6 @@ public SavegameType getType() {
128
137
return type ;
129
138
}
130
139
131
- public record SavegamePart (String name , String identifier ) {
140
+ public record SavegamePart (String fileName , String identifier ) {
132
141
}
133
142
}
0 commit comments