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

wurstscript / WurstScript / 224

23 Nov 2023 06:45PM UTC coverage: 62.574% (+0.01%) from 62.564%
224

push

circleci

web-flow
correctly generate .imp file with transitive imports (#1082)

17311 of 27665 relevant lines covered (62.57%)

0.63 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.ByteBuffer;
16
import java.nio.ByteOrder;
17
import java.nio.charset.StandardCharsets;
18
import java.nio.file.Path;
19
import java.util.*;
20
import java.util.stream.Collectors;
21
import java.util.stream.Stream;
22

23
public class ImportFile {
×
24
    private static final String DEFAULT_IMPORT_PATH = "war3mapImported\\";
25
    private static final int FILE_VERSION = 1;
26

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

37
        try {
38
            File projectFolder = mapFile.getParentFile();
×
39
            File importDirectory = getImportDirectory(projectFolder);
×
40
            File tempMap = getCopyOfMap(mapFile);
×
41

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

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

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

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

78
            for (int i = 1; i <= fileCount; i++) {
×
79
                extractImportedFile(mpq, directory, failed, reader);
×
80
            }
81

82
            return failed;
×
83
        } catch (Exception e) {
×
84
            throw new RuntimeException(e);
×
85
        }
86
    }
87

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

97
        String filename = readString(reader);
×
98
        WLogger.info("Extracting file: " + filename);
×
99

100
        filename = filename.trim();
×
101
        mpqpath += filename;
×
102
        path += filename;
×
103

104
        extractFile(mpq, directory, failed, path, mpqpath, filename);
×
105
    }
×
106

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

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

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

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

161
    }
162

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

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

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

196
        folders.removeIf(folder -> !folder.exists());
×
197

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

205
    }
×
206

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

214
    private static File getImportDirectory(File projectFolder) {
215
        return new File(projectFolder, "imports");
×
216
    }
217

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

234
}
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