Skip to content

Commit c4c1499

Browse files
authored
Second try to add Lua support (#867)
* Revert "Revert "Merge branch 'lua'"" This reverts commit 6db5d09, which reverted merging the Lua branch into master * fixed merge syntax error * fixed wrong translation of default value (see #852) * avoid NPE reported by frotty in commit 6db5d09 * Apply project config on runmap and and set lua flag for lua builds * add error messages to lua * fix lua array initialization and translation of null * improved handling of generics w/ ints * lua stacktrace improvements * fixed lua casting enums to int * fix lua: null instanceof something * fixed or ignored failing lua unit tests
1 parent 7ba7167 commit c4c1499

39 files changed

+2029
-1025
lines changed

de.peeeq.wurstscript/parserspec/jass_im.parseq

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ ImType =
2727
| ImVoid()
2828
| ImClassType(ref ImClass classDef, ImTypeArguments typeArguments)
2929
| ImTypeVarRef(ref ImTypeVar typeVariable)
30+
| ImAnyType()
3031

3132
ImTypeVars * ImTypeVar
3233

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/Main.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import de.peeeq.wurstio.gui.WurstGuiImpl;
1010
import de.peeeq.wurstio.hotdoc.HotdocGenerator;
1111
import de.peeeq.wurstio.languageserver.LanguageServerStarter;
12-
import de.peeeq.wurstio.languageserver.requests.BuildMap;
12+
import de.peeeq.wurstio.languageserver.ProjectConfigBuilder;
1313
import de.peeeq.wurstio.map.importer.ImportFile;
1414
import de.peeeq.wurstio.mpq.MpqEditor;
1515
import de.peeeq.wurstio.mpq.MpqEditorFactory;
@@ -29,7 +29,7 @@
2929
import java.nio.file.StandardCopyOption;
3030
import java.util.List;
3131

32-
import static de.peeeq.wurstio.languageserver.requests.BuildMap.FILE_NAME;
32+
import static de.peeeq.wurstio.languageserver.ProjectConfigBuilder.FILE_NAME;
3333

3434
public class Main {
3535

@@ -150,7 +150,7 @@ public static void main(String[] args) {
150150
Files.write(compiledScript.toString().getBytes(Charsets.UTF_8), scriptFile);
151151

152152
if (projectConfig != null && target != null) {
153-
BuildMap.applyProjectConfig(projectConfig, target.toFile(), scriptFile, buildDir.toFile());
153+
ProjectConfigBuilder.apply(projectConfig, target.toFile(), scriptFile, buildDir.toFile(), runArgs);
154154

155155
WLogger.info("map build success");
156156
System.out.println("Build succeeded. Output file: <" + target.toAbsolutePath() + ">");

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import java.io.*;
3838
import java.util.*;
3939
import java.util.Map.Entry;
40-
import java.util.function.Consumer;
4140
import java.util.function.Function;
4241

4342
import static de.peeeq.wurstio.CompiletimeFunctionRunner.FunctionFlagToRun.CompiletimeFunctions;
@@ -581,7 +580,7 @@ private ImTranslator getImTranslator() {
581580
public @Nullable ImProg translateProgToIm(WurstModel root) {
582581
beginPhase(1, "to intermediate lang");
583582
// translate wurst to intermediate lang:
584-
imTranslator = new ImTranslator(root, errorHandler.isUnitTestMode());
583+
imTranslator = new ImTranslator(root, errorHandler.isUnitTestMode(), runArgs);
585584
imProg = getImTranslator().translateProg();
586585
int stage = 1;
587586
printDebugImProg("./test-output/im " + stage++ + ".im");
@@ -799,6 +798,18 @@ public void setMapFile(File mapFile) {
799798
}
800799

801800
public LuaCompilationUnit transformProgToLua() {
801+
802+
if (runArgs.isNoDebugMessages()) {
803+
beginPhase(3, "remove debug messages");
804+
DebugMessageRemover.removeDebugMessages(imProg);
805+
} else {
806+
// debug: add stacktraces
807+
if (runArgs.isIncludeStacktraces()) {
808+
beginPhase(4, "add stack traces");
809+
new StackTraceInjector2(imProg, imTranslator).transform(timeTaker);
810+
}
811+
}
812+
802813
LuaTranslator luaTranslator = new LuaTranslator(imProg, imTranslator);
803814
LuaCompilationUnit luaCode = luaTranslator.translate();
804815
return luaCode;
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package de.peeeq.wurstio.languageserver;
2+
3+
import com.google.common.io.Files;
4+
import config.*;
5+
import de.peeeq.wurstio.Pjass;
6+
import de.peeeq.wurstio.languageserver.requests.RequestFailedException;
7+
import de.peeeq.wurstio.mpq.MpqEditor;
8+
import de.peeeq.wurstio.mpq.MpqEditorFactory;
9+
import de.peeeq.wurstscript.RunArgs;
10+
import net.moonlightflower.wc3libs.bin.app.MapHeader;
11+
import net.moonlightflower.wc3libs.bin.app.W3I;
12+
import net.moonlightflower.wc3libs.dataTypes.app.Controller;
13+
import org.apache.commons.lang.StringUtils;
14+
import org.eclipse.lsp4j.MessageType;
15+
16+
import java.io.File;
17+
import java.io.FileInputStream;
18+
import java.io.IOException;
19+
import java.io.StringWriter;
20+
import java.nio.charset.StandardCharsets;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import java.util.Optional;
24+
25+
public class ProjectConfigBuilder {
26+
public static final String FILE_NAME = "wurst.build";
27+
28+
public static void apply(WurstProjectConfigData projectConfig, File targetMap, File compiledScript, File buildDir, RunArgs runArgs) throws IOException {
29+
if (projectConfig.getProjectName().isEmpty()) {
30+
throw new RequestFailedException(MessageType.Error, "wurst.build is missing projectName.");
31+
}
32+
33+
34+
try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) {
35+
File file = new File(buildDir, "wc3libs.j");
36+
byte[] scriptBytes;
37+
if (!projectConfig.getBuildMapData().getName().isEmpty()) {
38+
// Apply w3i config values
39+
W3I w3I = prepareW3I(projectConfig, targetMap);
40+
FileInputStream inputStream = new FileInputStream(compiledScript);
41+
StringWriter sw = new StringWriter();
42+
w3I.injectConfigsInJassScript(inputStream, sw);
43+
44+
scriptBytes = sw.toString().getBytes(StandardCharsets.UTF_8);
45+
46+
File w3iFile = new File("w3iFile");
47+
if (runArgs.isLua()) {
48+
w3I.setScriptLang(W3I.SCRIPT_LANG_LUA);
49+
w3I.setFileVersion(W3I.EncodingFormat.W3I_0x1C.getVersion());
50+
}
51+
w3I.write(w3iFile);
52+
53+
mpq.deleteFile("war3map.w3i");
54+
mpq.insertFile("war3map.w3i", java.nio.file.Files.readAllBytes(w3iFile.toPath()));
55+
56+
w3iFile.delete();
57+
} else {
58+
scriptBytes = java.nio.file.Files.readAllBytes(compiledScript.toPath());
59+
}
60+
61+
Files.write(scriptBytes, file);
62+
Pjass.runPjass(file);
63+
mpq.deleteFile("war3map.j");
64+
mpq.insertFile("war3map.j", scriptBytes);
65+
66+
file.delete();
67+
} catch (Exception e) {
68+
throw new RuntimeException(e);
69+
}
70+
71+
applyMapHeader(projectConfig, targetMap);
72+
}
73+
74+
private static W3I prepareW3I(WurstProjectConfigData projectConfig, File targetMap) throws Exception {
75+
try (MpqEditor mpq = MpqEditorFactory.getEditor((targetMap))) {
76+
W3I w3I = new W3I(mpq.extractFile("war3map.w3i"));
77+
WurstProjectBuildMapData buildMapData = projectConfig.getBuildMapData();
78+
if (StringUtils.isNotBlank(buildMapData.getName())) {
79+
w3I.setMapName(buildMapData.getName());
80+
}
81+
if (StringUtils.isNotBlank(buildMapData.getAuthor())) {
82+
w3I.setMapAuthor(buildMapData.getAuthor());
83+
}
84+
applyScenarioData(w3I, buildMapData);
85+
86+
if (buildMapData.getPlayers().size() > 0) {
87+
applyPlayers(projectConfig, w3I);
88+
}
89+
if (buildMapData.getForces().size() > 0) {
90+
applyForces(projectConfig, w3I);
91+
}
92+
return w3I;
93+
}
94+
}
95+
96+
private static void applyScenarioData(W3I w3I, WurstProjectBuildMapData buildMapData) {
97+
WurstProjectBuildScenarioData scenarioData = buildMapData.getScenarioData();
98+
if (StringUtils.isNotBlank(scenarioData.getSuggestedPlayers())) {
99+
w3I.setPlayersRecommendedAmount(scenarioData.getSuggestedPlayers());
100+
}
101+
if (StringUtils.isNotBlank(scenarioData.getDescription())) {
102+
w3I.setMapDescription(scenarioData.getDescription());
103+
}
104+
if (scenarioData.getLoadingScreen() != null) {
105+
applyLoadingScreen(w3I, scenarioData.getLoadingScreen());
106+
}
107+
}
108+
109+
private static void applyLoadingScreen(W3I w3I, WurstProjectBuildLoadingScreenData loadingScreen) {
110+
w3I.setLoadingScreenModel(loadingScreen.getModel());
111+
w3I.getLoadingScreen().setTitle(loadingScreen.getTitle());
112+
w3I.getLoadingScreen().setSubtitle(loadingScreen.getSubTitle());
113+
w3I.getLoadingScreen().setText(loadingScreen.getText());
114+
}
115+
116+
private static void applyForces(WurstProjectConfigData projectConfig, W3I w3I) {
117+
w3I.clearForces();
118+
ArrayList<WurstProjectBuildForce> forces = projectConfig.getBuildMapData().getForces();
119+
for (WurstProjectBuildForce wforce : forces) {
120+
W3I.Force force = w3I.addForce();
121+
System.err.println("Setting name: " + wforce.getName());
122+
force.setName(wforce.getName());
123+
force.setFlag(W3I.Force.Flags.Flag.ALLIED, wforce.getFlags().getAllied());
124+
force.setFlag(W3I.Force.Flags.Flag.ALLIED_VICTORY, wforce.getFlags().getAlliedVictory());
125+
force.setFlag(W3I.Force.Flags.Flag.SHARED_VISION, wforce.getFlags().getSharedVision());
126+
force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL, wforce.getFlags().getSharedControl());
127+
force.setFlag(W3I.Force.Flags.Flag.SHARED_UNIT_CONTROL_ADVANCED, wforce.getFlags().getSharedControlAdvanced());
128+
force.addPlayerNums(wforce.getPlayerIds());
129+
}
130+
}
131+
132+
private static void applyPlayers(WurstProjectConfigData projectConfig, W3I w3I) {
133+
List<W3I.Player> existing = new ArrayList<>(w3I.getPlayers());
134+
w3I.getPlayers().clear();
135+
ArrayList<WurstProjectBuildPlayer> players = projectConfig.getBuildMapData().getPlayers();
136+
for (WurstProjectBuildPlayer wplayer : players) {
137+
Optional<W3I.Player> old = existing.stream().filter(player -> player.getNum() == wplayer.getId()).findFirst();
138+
W3I.Player player = w3I.addPlayer();
139+
player.setNum(wplayer.getId());
140+
141+
old.ifPresent(player1 -> applyExistingPlayerConfig(player1, player));
142+
143+
setVolatilePlayerConfig(wplayer, player);
144+
}
145+
}
146+
147+
private static void applyExistingPlayerConfig(W3I.Player oldPlayer, W3I.Player player) {
148+
player.setStartPos(oldPlayer.getStartPos());
149+
player.setName(oldPlayer.getName());
150+
player.setRace(oldPlayer.getRace());
151+
player.setType(oldPlayer.getType());
152+
player.setStartPosFixed(oldPlayer.getStartPosFixed());
153+
player.setAllyLowPrioFlags(oldPlayer.getAllyLowPrioFlags());
154+
player.setAllyHighPrioFlags(oldPlayer.getAllyHighPrioFlags());
155+
}
156+
157+
private static void setVolatilePlayerConfig(WurstProjectBuildPlayer wplayer, W3I.Player player) {
158+
if (wplayer.getName() != null) {
159+
player.setName(wplayer.getName());
160+
}
161+
162+
if (wplayer.getRace() != null) {
163+
W3I.Player.UnitRace val = W3I.Player.UnitRace.valueOf(wplayer.getRace().toString());
164+
if (val != null) {
165+
player.setRace(val);
166+
}
167+
}
168+
if (wplayer.getController() != null) {
169+
net.moonlightflower.wc3libs.dataTypes.app.Controller val1 = Controller.valueOf(wplayer.getController().toString());
170+
if (val1 != null) {
171+
player.setType(val1);
172+
}
173+
}
174+
if (wplayer.getFixedStartLoc() != null) {
175+
player.setStartPosFixed(wplayer.getFixedStartLoc() ? 1 : 0);
176+
}
177+
}
178+
179+
private static void applyMapHeader(WurstProjectConfigData projectConfig, File targetMap) throws IOException {
180+
MapHeader mapHeader = MapHeader.ofFile(targetMap);
181+
if (projectConfig.getBuildMapData().getPlayers().size() > 0) {
182+
mapHeader.setMaxPlayersCount(projectConfig.getBuildMapData().getPlayers().size());
183+
}
184+
if (StringUtils.isNotBlank(projectConfig.getBuildMapData().getName())) {
185+
mapHeader.setMapName(projectConfig.getBuildMapData().getName());
186+
}
187+
mapHeader.writeToMapFile(targetMap);
188+
}
189+
}

0 commit comments

Comments
 (0)