• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 228

29 Nov 2023 05:00PM UTC coverage: 62.48% (-0.09%) from 62.574%
228

push

circleci

web-flow
Show dialog for choosing game path, cleanup (#1083)

* show dialog for choosing game path

* cleanup code

* remove logs and refactor

* remove confusing mpq error, make some mpq loads readonly

17295 of 27681 relevant lines covered (62.48%)

0.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/map/importer/ImportFile.java
1
package de.peeeq.wurstio.map.importer;
2

3
import com.google.common.io.Files;
4
import com.google.common.io.LittleEndianDataInputStream;
5
import de.peeeq.wurstio.mpq.MpqEditor;
6
import de.peeeq.wurstio.mpq.MpqEditorFactory;
7
import de.peeeq.wurstscript.RunArgs;
8
import de.peeeq.wurstscript.WLogger;
9
import de.peeeq.wurstscript.utils.TempDir;
10
import net.moonlightflower.wc3libs.bin.Wc3BinOutputStream;
11
import net.moonlightflower.wc3libs.bin.app.IMP;
12

13
import javax.swing.*;
14
import java.io.*;
15
import java.nio.file.Path;
16
import java.util.*;
17
import java.util.stream.Collectors;
18
import java.util.stream.Stream;
19

20
public class ImportFile {
×
21
    private static final String DEFAULT_IMPORT_PATH = "war3mapImported\\";
22
    private static final int FILE_VERSION = 1;
23

24
    /**
25
     * Use this to start the extraction process
26
     */
27
    public static void extractImportsFromMap(File mapFile, RunArgs runArgs) {
28
        WLogger.info("Extracting all imported Files...");
×
29
        if (!mapFile.exists() || !mapFile.isFile() || mapFile.getName().endsWith("w3m")) {
×
30
            JOptionPane.showMessageDialog(null, "Map " + mapFile.getAbsolutePath() + " does not exist or is of wrong format (w3x only)");
×
31
            return;
×
32
        }
33

34
        try {
35
            File projectFolder = mapFile.getParentFile();
×
36
            File importDirectory = getImportDirectory(projectFolder);
×
37
            File tempMap = getCopyOfMap(mapFile);
×
38

39
            extractImportsFrom(importDirectory, tempMap, runArgs);
×
40
        } catch (Exception e) {
×
41
            WLogger.severe(e);
×
42
            JOptionPane.showMessageDialog(null, "Could not export objects (2): " + e.getMessage());
×
43
        }
×
44
    }
×
45

46
    private static void extractImportsFrom(File importDirectory, File tempMap, RunArgs runArgs) throws Exception {
47
        try (MpqEditor editor = MpqEditorFactory.getEditor(Optional.of(tempMap), true)) {
×
48
            LinkedList<String> failed = extractImportedFiles(editor, importDirectory);
×
49

50
            if (failed.isEmpty()) {
×
51
                JOptionPane.showMessageDialog(null, "All imports were extracted to " + importDirectory.getAbsolutePath());
×
52
            } else {
53
                String message = "Following files could not be extracted:\n" + String.join(",", failed);
×
54
                WLogger.info(message);
×
55
                JOptionPane.showMessageDialog(null, message);
×
56
            }
57
        }
58
    }
×
59

60
    private static LinkedList<String> extractImportedFiles(MpqEditor mpq, File directory) {
61
        LinkedList<String> failed = new LinkedList<>();
×
62
        byte[] temp;
63
        try {
64
            temp = mpq.extractFile("war3map.imp");
×
65
        } catch (Exception e1) {
×
66
            JOptionPane.showMessageDialog(null, "No vaild war3map.imp was found, or there are no imports");
×
67
            return failed;
×
68
        }
×
69
        try (LittleEndianDataInputStream reader = new LittleEndianDataInputStream(new ByteArrayInputStream(temp))) {
×
70
            @SuppressWarnings("unused")
71
            int fileFormatVersion = reader.readInt(); // Not needed
×
72
            int fileCount = reader.readInt();
×
73
            WLogger.info("Imported FileCount: " + fileCount);
×
74

75
            for (int i = 1; i <= fileCount; i++) {
×
76
                extractImportedFile(mpq, directory, failed, reader);
×
77
            }
78

79
            return failed;
×
80
        } catch (Exception e) {
×
81
            throw new RuntimeException(e);
×
82
        }
83
    }
84

85
    private static void extractImportedFile(MpqEditor mpq, File directory, LinkedList<String> failed, LittleEndianDataInputStream reader) throws Exception {
86
        byte b = reader.readByte();
×
87
        String path = directory.getPath() + "\\";
×
88
        String mpqpath = "";
×
89
        if (isStandardPath(b)) {
×
90
            path += DEFAULT_IMPORT_PATH;
×
91
            mpqpath += DEFAULT_IMPORT_PATH;
×
92
        }
93

94
        String filename = readString(reader);
×
95
        WLogger.info("Extracting file: " + filename);
×
96

97
        filename = filename.trim();
×
98
        mpqpath += filename;
×
99
        path += filename;
×
100

101
        extractFile(mpq, directory, failed, path, mpqpath, filename);
×
102
    }
×
103

104
    private static void extractFile(MpqEditor mpq, File directory, LinkedList<String> failed, String path, String mpqpath, String filename) throws Exception {
105
        File out = new File(path);
×
106
        out.getParentFile().mkdirs();
×
107
        try {
108
            byte[] xx = mpq.extractFile(mpqpath);
×
109
            Files.write(xx, out);
×
110
        } catch (IOException e) {
×
111
            out.delete();
×
112
            out = new File(directory.getPath() + "\\" + DEFAULT_IMPORT_PATH + filename);
×
113
            out.getParentFile().mkdirs();
×
114
            try {
115
                byte[] xx = mpq.extractFile(DEFAULT_IMPORT_PATH + mpqpath);
×
116
                Files.write(xx, out);
×
117
            } catch (IOException e1) {
×
118
                failed.add(mpqpath);
×
119
            }
×
120
        }
×
121
    }
×
122

123
    /**
124
     * Blizzard magic numbers for standard path
125
     */
126
    private static boolean isStandardPath(byte b) {
127
        return b == 5 || b == 8;
×
128
    }
129

130
    /**
131
     * Reads chars from the inputstream until it hits a 0-char
132
     */
133
    private static String readString(LittleEndianDataInputStream reader) throws IOException {
134
        StringBuilder sb = new StringBuilder();
×
135
        try {
136
            while (true) {
137
                char c = (char) reader.readByte();
×
138
                if (c == 0) {
×
139
                    return sb.toString();
×
140
                }
141
                sb.append(c);
×
142
            }
×
143
        } catch (EOFException e) {
×
144
            return sb.toString();
×
145
        }
146
    }
147

148
    private static LinkedList<File> getFilesOfDirectory(File dir, LinkedList<File> addTo) {
149
        for (File f : dir.listFiles()) {
×
150
            if (f.isDirectory()) {
×
151
                getFilesOfDirectory(f, addTo);
×
152
            } else {
153
                addTo.add(f);
×
154
            }
155
        }
156
        return addTo;
×
157

158
    }
159

160
    private static void insertImportedFiles(MpqEditor mpq, List<File> directories) throws Exception {
161
        IMP importFile = new IMP();
×
162
        for (File directory : directories) {
×
163
            LinkedList<File> files = new LinkedList<>();
×
164
            getFilesOfDirectory(directory, files);
×
165

166
            for (File f : files) {
×
167
                Path p = f.toPath();
×
168
                p = directory.toPath().relativize(p);
×
169
                String normalizedWc3Path = p.toString().replaceAll("/", "\\\\");
×
170
                IMP.Obj importObj = new IMP.Obj();
×
171
                importObj.setPath(normalizedWc3Path);
×
172
                importObj.setStdFlag(IMP.StdFlag.CUSTOM);
×
173
                importFile.addObj(importObj);
×
174
                mpq.deleteFile(normalizedWc3Path);
×
175
                mpq.insertFile(normalizedWc3Path, f);
×
176
            }
×
177
        }
×
178
        mpq.deleteFile(IMP.GAME_PATH);
×
179
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
×
180
        try (Wc3BinOutputStream wc3BinOutputStream = new Wc3BinOutputStream(byteArrayOutputStream)) {
×
181
            importFile.write(wc3BinOutputStream);
×
182
        }
183
        byteArrayOutputStream.flush();
×
184
        byte[] byteArray = byteArrayOutputStream.toByteArray();
×
185
        mpq.insertFile(IMP.GAME_PATH, byteArray);
×
186
    }
×
187

188
    public static void importFilesFromImports(File projectFolder, MpqEditor ed) {
189
        LinkedList<File> folders = new LinkedList<>();
×
190
        folders.add(getImportDirectory(projectFolder));
×
191
        folders.addAll(Arrays.asList(getTransientImportDirectories(projectFolder)));
×
192

193
        folders.removeIf(folder -> !folder.exists());
×
194

195
        try {
196
            insertImportedFiles(ed, folders);
×
197
        } catch (Exception e) {
×
198
            WLogger.severe(e);
×
199
            JOptionPane.showMessageDialog(null, "Couldn't import resources. " + e.getMessage());
×
200
        }
×
201

202
    }
×
203

204
    private static File getCopyOfMap(File mapFile) throws IOException {
205
        File mapTemp = File.createTempFile("temp", "w3x", TempDir.get());
×
206
        mapTemp.deleteOnExit();
×
207
        Files.copy(mapFile, mapTemp);
×
208
        return mapTemp;
×
209
    }
210

211
    private static File getImportDirectory(File projectFolder) {
212
        return new File(projectFolder, "imports");
×
213
    }
214

215
    private static File[] getTransientImportDirectories(File projectFolder) {
216
        ArrayList<Path> paths = new ArrayList<>();
×
217
        Path dependencies = projectFolder.toPath().resolve("_build").resolve("dependencies");
×
218
        try (Stream<Path> spaths = java.nio.file.Files.list(dependencies)) {
×
219
            spaths.forEach(dependency -> {
×
220
                if (java.nio.file.Files.exists(dependency.resolve("imports"))) {
×
221
                    paths.add(dependency.resolve("imports"));
×
222
                }
223
            });
×
224
        } catch (IOException e) {
×
225
            e.printStackTrace();
×
226
        }
×
227
        File[] arr = new File[paths.size()];
×
228
        return paths.stream().map(Path::toFile).collect(Collectors.toList()).toArray(arr);
×
229
    }
230

231
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc