Coveralls logob
Coveralls logo
  • Home
  • Features
  • Pricing
  • Docs
  • Sign In

wurstscript / WurstScript / 1005

21 Mar 2019 - 22:31 coverage decreased (-0.09%) to 61.245%
1005

Pull #822

travis-ci

9181eb84f9c35729a3bad740fb7f9d93?size=18&default=identiconweb-flow
more new bug fixes
Pull Request #822: WIP: support for persisting objects in compiletime expressions

14931 of 24379 relevant lines covered (61.25%)

0.61 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/languageserver/requests/BuildMap.java
1
package de.peeeq.wurstio.languageserver.requests;
2

3
import com.google.common.io.Files;
4
import config.*;
5
import de.peeeq.wurstio.Pjass;
6
import de.peeeq.wurstio.gui.WurstGuiImpl;
7
import de.peeeq.wurstio.languageserver.ModelManager;
8
import de.peeeq.wurstio.languageserver.WFile;
9
import de.peeeq.wurstio.mpq.MpqEditor;
10
import de.peeeq.wurstio.mpq.MpqEditorFactory;
11
import de.peeeq.wurstscript.RunArgs;
12
import de.peeeq.wurstscript.WLogger;
13
import de.peeeq.wurstscript.ast.CompilationUnit;
14
import de.peeeq.wurstscript.ast.WurstModel;
15
import de.peeeq.wurstscript.attributes.CompileError;
16
import de.peeeq.wurstscript.gui.WurstGui;
17
import net.moonlightflower.wc3libs.bin.app.MapHeader;
18
import net.moonlightflower.wc3libs.bin.app.W3I;
19
import net.moonlightflower.wc3libs.dataTypes.app.Controller;
20
import org.eclipse.lsp4j.MessageType;
21

22
import java.io.File;
23
import java.io.FileInputStream;
24
import java.io.IOException;
25
import java.io.StringWriter;
26
import java.nio.charset.StandardCharsets;
27
import java.util.ArrayList;
28
import java.util.List;
29
import java.util.Optional;
30

31
/**
32
 * Created by peter on 16.05.16.
33
 */
34
public class BuildMap extends MapRequest {
35
    private static final String FILE_NAME = "wurst.build";
36

37
    /**
38
     * makes the compilation slower, but more safe by discarding results from the editor and working on a copy of the model
39
     */
UNCOV
40
    private SafetyLevel safeCompilation = SafetyLevel.KindOfSafe;
!
41

42
    enum SafetyLevel {
!
UNCOV
43
        QuickAndDirty, KindOfSafe
!
44
    }
45

46
    public BuildMap(WFile workspaceRoot, File map, List<String> compileArgs) {
47
        super(map, compileArgs, workspaceRoot);
!
UNCOV
48
    }
!
49

50

51
    @Override
52
    public Object execute(ModelManager modelManager) throws IOException {
53
        if (modelManager.hasErrors()) {
!
UNCOV
54
            throw new RequestFailedException(MessageType.Error, "Fix errors in your code before building a release.");
!
55
        }
56

57
        WurstProjectConfigData projectConfig = WurstProjectConfig.INSTANCE.loadProject(workspaceRoot.getFile().toPath().resolve(FILE_NAME));
!
58
        if (projectConfig == null) {
!
UNCOV
59
            throw new RequestFailedException(MessageType.Error, FILE_NAME + " file doesn't exist or is invalid. " +
!
60
                    "Please refresh your project using an up to date wurst setup tool.");
61
        }
62

63
        // TODO use normal compiler for this, avoid code duplication
64
        WLogger.info("buildMap " + map.getAbsolutePath() + " " + compileArgs);
!
UNCOV
65
        WurstGui gui = new WurstGuiImpl(workspaceRoot.getFile().getAbsolutePath());
!
66
        try {
67
            if (!map.exists()) {
!
UNCOV
68
                throw new RequestFailedException(MessageType.Error, map.getAbsolutePath() + " does not exist.");
!
69
            }
70

UNCOV
71
            gui.sendProgress("Copying map");
!
72

73
            // first we copy in same location to ensure validity
74
            File buildDir = getBuildDir();
!
75
            File targetMap = new File(buildDir, projectConfig.getBuildMapData().getFileName() + ".w3x");
!
76
            if (targetMap.exists()) {
!
77
                boolean deleteOk = targetMap.delete();
!
78
                if (!deleteOk) {
!
UNCOV
79
                    throw new RequestFailedException(MessageType.Error, "Could not delete old mapfile: " + targetMap);
!
80
                }
81
            }
UNCOV
82
            Files.copy(map, targetMap);
!
83

84

85
            // first compile the script:
UNCOV
86
            File compiledScript = compileScript(gui, modelManager, compileArgs, targetMap, map);
!
87

88
            WurstModel model = modelManager.getModel();
!
89
            if (model == null || model.stream().noneMatch((CompilationUnit cu) -> cu.getFile().endsWith("war3map.j"))) {
!
90
                println("No 'war3map.j' file could be found inside the map nor inside the wurst folder");
!
91
                println("If you compile the map with WurstPack once, this file should be in your wurst-folder. ");
!
UNCOV
92
                println("We will try to start the map now, but it will probably fail. ");
!
93
            }
94

95
            gui.sendProgress("Applying Map Config...");
!
UNCOV
96
            applyProjectConfig(projectConfig, targetMap, compiledScript);
!
97

98
            gui.sendProgress("Done.");
!
99
        } catch (CompileError e) {
!
100
            WLogger.info(e);
!
101
            throw new RequestFailedException(MessageType.Error, "There was an error when compiling the map:\n" + e);
!
102
        } catch (RuntimeException e) {
!
103
            throw e;
!
104
        } catch (final Exception e) {
!
UNCOV
105
            throw new RuntimeException(e);
!
106
        } finally {
UNCOV
107
            gui.sendFinished();
!
108
        }
UNCOV
109
        return "ok"; // TODO
!
110
    }
111

112
    private W3I prepareW3I(WurstProjectConfigData projectConfig, File targetMap) throws Exception {
113
        try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) {
!
114
            W3I w3I = new W3I(mpq.extractFile("war3map.w3i"));
!
115
            WurstProjectBuildMapData buildMapData = projectConfig.getBuildMapData();
!
116
            w3I.setMapName(buildMapData.getName());
!
117
            w3I.setMapAuthor(buildMapData.getAuthor());
!
118
            WurstProjectBuildScenarioData scenarioData = buildMapData.getScenarioData();
!
119
            w3I.setPlayersRecommendedAmount(scenarioData.getSuggestedPlayers());
!
UNCOV
120
            w3I.setMapDescription(scenarioData.getDescription());
!
121

122
            if (buildMapData.getPlayers().size() > 0) {
!
UNCOV
123
                applyPlayers(projectConfig, w3I);
!
124
            }
125
            if (buildMapData.getForces().size() > 0) {
!
UNCOV
126
                applyForces(projectConfig, w3I);
!
127
            }
128
            if (scenarioData.getLoadingScreen() != null) {
!
UNCOV
129
                applyLoadingScreen(w3I, scenarioData.getLoadingScreen());
!
130
            }
UNCOV
131
            return w3I;
!
132
        }
133
    }
134

135
  private void applyProjectConfig(WurstProjectConfigData projectConfig, File targetMap, File compiledScript) throws IOException {
136
        if (projectConfig.getBuildMapData().getFileName().isEmpty()) {
!
UNCOV
137
            throw new RequestFailedException(MessageType.Error, "wurst.build is missing mapFileName");
!
138
        }
139

140
        if (!projectConfig.getBuildMapData().getName().isEmpty()) {
!
UNCOV
141
            try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) {
!
142

143
                // Apply w3i config values
144
                W3I w3I = prepareW3I(projectConfig, targetMap);
!
145
                FileInputStream inputStream = new FileInputStream(compiledScript);
!
146
                StringWriter sw = new StringWriter();
!
UNCOV
147
                w3I.injectConfigsInJassScript(inputStream, sw);
!
148

149
                File file = new File(getBuildDir(), "wc3libs.j");
!
150
                byte[] scriptBytes = sw.toString().getBytes(StandardCharsets.UTF_8);
!
151
                Files.write(scriptBytes, file);
!
152
                Pjass.runPjass(file);
!
UNCOV
153
                mpq.insertFile("war3map.j", scriptBytes);
!
154

155
                File w3iFile = new File("w3iFile");
!
UNCOV
156
                w3I.write(w3iFile);
!
157

158
                mpq.deleteFile("war3map.w3i");
!
159
                mpq.insertFile("war3map.w3i", java.nio.file.Files.readAllBytes(w3iFile.toPath()));
!
160
                file.delete();
!
161
                w3iFile.delete();
!
162
            } catch (Exception e) {
!
163
                throw new RuntimeException(e);
!
UNCOV
164
            }
!
165
        }
166

167
        applyMapHeader(projectConfig, targetMap);
!
UNCOV
168
    }
!
169

170
    private void applyLoadingScreen(W3I w3I, WurstProjectBuildLoadingScreenData loadingScreen) {
171
        w3I.setLoadingScreenModel(loadingScreen.getModel());
!
172
        w3I.getLoadingScreen().setTitle(loadingScreen.getTitle());
!
173
        w3I.getLoadingScreen().setSubtitle(loadingScreen.getSubTitle());
!
174
        w3I.getLoadingScreen().setText(loadingScreen.getText());
!
UNCOV
175
    }
!
176

177
    private void applyForces(WurstProjectConfigData projectConfig, W3I w3I) {
178
        w3I.clearForces();
!
179
        ArrayList<WurstProjectBuildForce> forces = projectConfig.getBuildMapData().getForces();
!
180
        for (WurstProjectBuildForce wforce : forces) {
!
181
            W3I.Force force = w3I.addForce();
!
182
            force.setName(wforce.getName());
!
183
            force.setFlag(W3I.Force.Flags.Flag.ALLIED, wforce.getFlags().getAllied());
!
184
            force.setFlag(W3I.Force.Flags.Flag.ALLIED_VICTORY, wforce.getFlags().getAlliedVictory());
!
185
            force.setFlag(W3I.Force.Flags.Flag.SHARED_VISION, wforce.getFlags().getSharedVision());
!
186
            force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL, wforce.getFlags().getSharedControl());
!
187
            force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL_ADVANCED, wforce.getFlags().getSharedControlAdvanced());
!
188
            force.addPlayerNums(wforce.getPlayerIds());
!
189
        }
!
UNCOV
190
    }
!
191

192
    private void applyPlayers(WurstProjectConfigData projectConfig, W3I w3I) {
193
                List<W3I.Player> existing = new ArrayList<>(w3I.getPlayers());
!
194
                w3I.getPlayers().clear();
!
195
        ArrayList<WurstProjectBuildPlayer> players = projectConfig.getBuildMapData().getPlayers();
!
196
        for (WurstProjectBuildPlayer wplayer : players) {
!
197
                        Optional<W3I.Player> old = existing.stream().filter(player -> player.getNum() == wplayer.getId()).findFirst();
!
198
                        W3I.Player player = w3I.addPlayer();
!
UNCOV
199
                        player.setNum(wplayer.getId());
!
200

UNCOV
201
                        old.ifPresent(player1 -> applyExistingPlayerConfig(player1, player));
!
202

203
                        setVolatilePlayerConfig(wplayer, player);
!
204
                }
!
UNCOV
205
    }
!
206

207
        private void applyExistingPlayerConfig(W3I.Player oldPlayer, W3I.Player player) {
208
                player.setStartPos(oldPlayer.getStartPos());
!
209
                player.setName(oldPlayer.getName());
!
210
                player.setRace(oldPlayer.getRace());
!
211
                player.setType(oldPlayer.getType());
!
212
                player.setStartPosFixed(oldPlayer.getStartPosFixed());
!
213
                player.setAllyLowPrioFlags(oldPlayer.getAllyLowPrioFlags());
!
214
                player.setAllyHighPrioFlags(oldPlayer.getAllyHighPrioFlags());
!
UNCOV
215
        }
!
216

217
        private void setVolatilePlayerConfig(WurstProjectBuildPlayer wplayer, W3I.Player player) {
218
                if(wplayer.getName() != null) {
!
UNCOV
219
                        player.setName(wplayer.getName());
!
220
                }
221

222
                if (wplayer.getRace() != null) {
!
223
                        W3I.Player.UnitRace val = W3I.Player.UnitRace.valueOf(wplayer.getRace().toString());
!
224
                        if (val != null) {
!
UNCOV
225
                                player.setRace(val);
!
226
                        }
227
                }
228
                if (wplayer.getController() != null) {
!
229
                        Controller val1 = Controller.valueOf(wplayer.getController().toString());
!
230
                        if (val1 != null) {
!
UNCOV
231
                                player.setType(val1);
!
232
                        }
233
                }
234
                if (wplayer.getFixedStartLoc() != null) {
!
UNCOV
235
                        player.setStartPosFixed(wplayer.getFixedStartLoc() ? 1 : 0);
!
236
                }
UNCOV
237
        }
!
238

239
        private void applyMapHeader(WurstProjectConfigData projectConfig, File targetMap) throws IOException {
240
        MapHeader mapHeader = MapHeader.ofFile(targetMap);
!
241
        mapHeader.setMaxPlayersCount(projectConfig.getBuildMapData().getPlayers().size());
!
242
        mapHeader.setMapName(projectConfig.getBuildMapData().getName());
!
243
        mapHeader.writeToMapFile(targetMap);
!
UNCOV
244
    }
!
245

246
    private File compileScript(WurstGui gui, ModelManager modelManager, List<String> compileArgs, File mapCopy, File origMap) throws Exception {
247
        gui.sendProgress("Compiling mapscript");
!
248
        RunArgs runArgs = new RunArgs(compileArgs);
!
249
        print("Compile Script : ");
!
250
        for (File dep : modelManager.getDependencyWurstFiles()) {
!
251
            WLogger.info("dep: " + dep.getPath());
!
252
        }
!
253
        print("Dependencies done.");
!
254
        processMapScript(runArgs, gui, modelManager, mapCopy);
!
255
        print("Processed mapscript");
!
UNCOV
256
        if (safeCompilation != SafetyLevel.QuickAndDirty) {
!
257
            // it is safer to rebuild the project, instead of taking the current editor state
258
            gui.sendProgress("Cleaning project");
!
259
            modelManager.clean();
!
260
            gui.sendProgress("Building project");
!
UNCOV
261
            modelManager.buildProject();
!
262
        }
263

264
        if (modelManager.hasErrors()) {
!
265
            for (CompileError compileError : modelManager.getParseErrors()) {
!
266
                gui.sendError(compileError);
!
267
            }
!
UNCOV
268
            throw new RequestFailedException(MessageType.Warning, "Cannot run code with syntax errors.");
!
269
        }
270

271
        WurstModel model = modelManager.getModel();
!
UNCOV
272
        if (safeCompilation != SafetyLevel.QuickAndDirty) {
!
273
            // compilation will alter the model (e.g. remove unused imports), 
274
            // so it is safer to create a copy
UNCOV
275
            model = ModelManager.copy(model);
!
276
        }
277

UNCOV
278
        return compileMap(modelManager.getProjectPath(), gui, mapCopy, origMap, runArgs, model);
!
279
    }
280

281
}
Troubleshooting · Open an Issue · Sales · Support · ENTERPRISE · CAREERS · STATUS
BLOG · TWITTER · Legal & Privacy · Supported CI Services · What's a CI service? · Automated Testing

© 2022 Coveralls, Inc