Update jass parsing systems to better support some test maps

This commit is contained in:
Retera 2021-09-20 01:16:35 -04:00
parent ca726eb2a3
commit e77afdb148
88 changed files with 1217 additions and 202 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

View File

@ -36,6 +36,7 @@ import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.units.Element;
import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Model;
import com.etheller.warsmash.viewer5.ModelInstance;
import com.etheller.warsmash.viewer5.ModelViewer;
@ -208,6 +209,11 @@ public class WarsmashGdxMapScreen implements InputProcessor, Screen {
}
this.commonEnv = Jass2.loadCommon(this.viewer.mapMpq, this.uiViewport, this.uiScene, this.viewer, this.meleeUI,
"Scripts\\common.j", "Scripts\\Blizzard.j", "war3map.j");
this.commonEnv.config();
if (WarsmashConstants.LOCAL_TEMP_TEST_ALL_PLAYERS_PLAYING) {
this.viewer.simulation.updateIsPlaying(this.viewer.getMapConfig());
}
this.commonEnv.main();
}
public static DataSource parseDataSources(final DataTable warsmashIni) {

View File

@ -1,5 +1,6 @@
package com.etheller.warsmash;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@ -28,6 +29,7 @@ import com.etheller.warsmash.parsers.jass.Jass2.RootFrameListener;
import com.etheller.warsmash.units.DataTable;
import com.etheller.warsmash.util.DataSourceFileHandle;
import com.etheller.warsmash.util.ImageUtils;
import com.etheller.warsmash.util.StringBundle;
import com.etheller.warsmash.util.WarsmashConstants;
import com.etheller.warsmash.viewer5.Camera;
import com.etheller.warsmash.viewer5.CanvasProvider;
@ -177,6 +179,16 @@ public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleMode
System.out.println("Loaded");
Gdx.gl30.glClearColor(0.0f, 0.0f, 0.0f, 1);
final DataTable musicSLK = new DataTable(StringBundle.EMPTY);
final String musicSLKPath = "UI\\SoundInfo\\Music.SLK";
if (this.viewer.dataSource.has(musicSLKPath)) {
try (InputStream miscDataTxtStream = this.viewer.dataSource.getResourceAsStream(musicSLKPath)) {
musicSLK.readSLK(miscDataTxtStream);
}
catch (final IOException e) {
e.printStackTrace();
}
}
this.menuUI = new MenuUI(this.viewer.dataSource, this.uiViewport, this.uiScene, this.viewer, this.game,
this, this.warsmashIni, new RootFrameListener() {
@ -188,9 +200,14 @@ public class WarsmashGdxMenuScreen implements InputProcessor, Screen, SingleMode
final String musicField = rootFrame
.getSkinField("GlueMusic_V" + WarsmashConstants.GAME_VERSION);
final String[] musics = musicField.split(";");
final String musicPath = musics[(int) (Math.random() * musics.length)];
String musicPath = musics[(int) (Math.random() * musics.length)];
if (musicSLK.get(musicPath) != null) {
musicPath = musicSLK.get(musicPath).getField("FileNames");
}
final String[] moreSplitMusics = musicPath.split(",");
final String finalMusicPath = moreSplitMusics[(int) (Math.random() * musics.length)];
final Music music = Gdx.audio.newMusic(new DataSourceFileHandle(
WarsmashGdxMenuScreen.this.viewer.dataSource, musicPath));
WarsmashGdxMenuScreen.this.viewer.dataSource, finalMusicPath));
// music.setVolume(0.2f);
music.setLooping(true);
music.play();

View File

@ -20,6 +20,7 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.viewport.Viewport;
import com.etheller.interpreter.JassLexer;
import com.etheller.interpreter.JassParser;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
@ -27,16 +28,19 @@ import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.interpreter.ast.scope.trigger.TriggerBooleanExpression;
import com.etheller.interpreter.ast.scope.variableevent.CLimitOp;
import com.etheller.interpreter.ast.util.CHandle;
import com.etheller.interpreter.ast.value.BooleanJassValue;
import com.etheller.interpreter.ast.value.HandleJassType;
import com.etheller.interpreter.ast.value.HandleJassValue;
import com.etheller.interpreter.ast.value.IntegerJassValue;
import com.etheller.interpreter.ast.value.JassType;
import com.etheller.interpreter.ast.value.JassValue;
import com.etheller.interpreter.ast.value.RealJassValue;
import com.etheller.interpreter.ast.value.StringJassValue;
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
import com.etheller.interpreter.ast.value.visitor.IntegerJassValueVisitor;
import com.etheller.interpreter.ast.value.visitor.JassFunctionJassValueVisitor;
import com.etheller.interpreter.ast.value.visitor.JassTypeGettingValueVisitor;
import com.etheller.interpreter.ast.value.visitor.ObjectJassValueVisitor;
import com.etheller.interpreter.ast.value.visitor.RealJassValueVisitor;
import com.etheller.interpreter.ast.value.visitor.StringJassValueVisitor;
@ -75,6 +79,8 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitEnumFunction;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnitType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.CAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.GetAbilityByRawcodeVisitor;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.inventory.CAbilityInventory;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityPointTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.ai.AIDifficulty;
@ -97,6 +103,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRacePrefer
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CStartLocPrio;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegion;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionTriggerEnter;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.region.CRegionTriggerLeave;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.sound.CMIDISound;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.sound.CSound;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.sound.CSoundFilename;
@ -125,6 +132,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.C
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CVersion;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes.CWeaponSoundTypeJass;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit.CUnitTypeJass;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.CHashtable;
import com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI;
public class Jass2 {
@ -163,6 +171,7 @@ public class Jass2 {
sourceName + "line " + line + ":" + charPositionInLine + " " + msg);
}
});
jassProgramVisitor.setCurrentFileName(jassFile);
jassProgramVisitor.visit(parser.program());
}
catch (final Exception e) {
@ -422,6 +431,7 @@ public class Jass2 {
}
public static final class CommonEnvironment {
private GameUI gameUI;
private Element skin;
private final JassProgramVisitor jassProgramVisitor;
@ -1459,8 +1469,8 @@ public class Jass2 {
final float radius = arguments.get(3).visit(RealJassValueVisitor.getInstance()).floatValue();
final TriggerBooleanExpression filter = nullable(arguments, 4,
ObjectJassValueVisitor.<TriggerBooleanExpression>getInstance());
simulation.getWorldCollision().enumUnitsInRect(tempRect.set(x - radius, y - radius, radius, radius),
new CUnitEnumFunction() {
simulation.getWorldCollision().enumUnitsInRect(
tempRect.set(x - radius, y - radius, radius * 2, radius * 2), new CUnitEnumFunction() {
@Override
public boolean call(final CUnit unit) {
@ -1723,9 +1733,14 @@ public class Jass2 {
final TriggerExecutionScope triggerScope) {
final List<CUnit> group = arguments.get(0).visit(ObjectJassValueVisitor.<List<CUnit>>getInstance());
final JassFunction callback = arguments.get(1).visit(JassFunctionJassValueVisitor.getInstance());
for (final CUnit unit : group) {
callback.call(Collections.<JassValue>emptyList(), globalScope,
CommonTriggerExecutionScope.enumScope(triggerScope, unit));
try {
for (final CUnit unit : group) {
callback.call(Collections.<JassValue>emptyList(), globalScope,
CommonTriggerExecutionScope.enumScope(triggerScope, unit));
}
}
catch (final Exception e) {
throw new JassException(globalScope, "Exception during ForGroup", e);
}
return null;
}
@ -1883,9 +1898,14 @@ public class Jass2 {
final List<CPlayerJass> force = arguments.get(0)
.visit(ObjectJassValueVisitor.<List<CPlayerJass>>getInstance());
final JassFunction callback = arguments.get(1).visit(JassFunctionJassValueVisitor.getInstance());
for (final CPlayerJass player : force) {
callback.call(Collections.<JassValue>emptyList(), globalScope,
CommonTriggerExecutionScope.enumScope(triggerScope, player));
try {
for (final CPlayerJass player : force) {
callback.call(Collections.<JassValue>emptyList(), globalScope,
CommonTriggerExecutionScope.enumScope(triggerScope, player));
}
}
catch (final Exception e) {
throw new JassException(globalScope, "Exception during ForForce", e);
}
return null;
}
@ -2415,10 +2435,10 @@ public class Jass2 {
final TriggerExecutionScope triggerScope) {
final Trigger trigger = arguments.get(0).visit(ObjectJassValueVisitor.<Trigger>getInstance());
final CRegion region = arguments.get(1).visit(ObjectJassValueVisitor.<CRegion>getInstance());
final TriggerBooleanExpression boolexpr = arguments.get(2)
.visit(ObjectJassValueVisitor.<TriggerBooleanExpression>getInstance());
final TriggerBooleanExpression boolexpr = nullable(arguments, 2,
ObjectJassValueVisitor.<TriggerBooleanExpression>getInstance());
return new HandleJassValue(eventType,
region.add(new CRegionTriggerEnter(globalScope, trigger, boolexpr)));
region.add(new CRegionTriggerLeave(globalScope, trigger, boolexpr)));
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetLeavingUnit", new JassFunction() {
@ -3029,6 +3049,9 @@ public class Jass2 {
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final Trigger whichTrigger = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
if (whichTrigger == null) {
return BooleanJassValue.FALSE;
}
return BooleanJassValue.of(whichTrigger.evaluate(globalScope, triggerScope));
}
});
@ -3271,6 +3294,58 @@ public class Jass2 {
new Point2D.Double(whichWidget.getX(), whichWidget.getY()));
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetUnitAbilityLevel", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichWidget = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final int rawcode = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final CAbility ability = whichWidget
.getAbility(GetAbilityByRawcodeVisitor.getInstance().reset(new War3ID(rawcode)));
// TODO below code is very stupid!!
return new IntegerJassValue(ability == null ? 0 : 1);
}
});
jassProgramVisitor.getJassNativeManager().createNative("IncUnitAbilityLevel", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichWidget = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final int rawcode = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final War3ID war3id = new War3ID(rawcode);
final CAbility ability = whichWidget
.getAbility(GetAbilityByRawcodeVisitor.getInstance().reset(war3id));
if (ability == null) {
whichWidget.add(simulation, simulation.getAbilityData().createAbility(war3id.toString(),
simulation.getHandleIdAllocator().createId()));
// TODO below code is very stupid!!
return new IntegerJassValue(1);
}
else {
// TODO below code is very stupid!!
return new IntegerJassValue(1);
}
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerHandicap", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CPlayer whichPlayer = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
return new RealJassValue(whichPlayer.getHandicap());
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetHandleId", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CHandle whichHandle = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
if (whichHandle == null) {
return IntegerJassValue.ZERO;
}
return new IntegerJassValue(whichHandle.getHandleId());
}
});
jassProgramVisitor.getJassNativeManager().createNative("AddSpecialEffectTarget", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
@ -3577,6 +3652,9 @@ public class Jass2 {
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
if (whichUnit == null) {
return playerType.getNullValue();
}
return new HandleJassValue(playerType, simulation.getPlayer(whichUnit.getPlayerIndex()));
}
});
@ -3667,6 +3745,164 @@ public class Jass2 {
return BooleanJassValue.of(group.contains(whichUnit));
}
});
// Patch 1.23+ crap
jassProgramVisitor.getJassNativeManager().createNative("InitHashtable", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
return new HandleJassValue(hashtableType, new CHashtable());
}
});
jassProgramVisitor.getJassNativeManager().createNative("SaveInteger", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveReal", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveBoolean", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveStr", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SavePlayerHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveWidgetHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveDestructableHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveItemHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveUnitHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveAbilityHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTimerHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTriggerHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTriggerConditionHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTriggerActionHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTriggerEventHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveForceHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveGroupHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveLocationHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveRectHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveBooleanExprHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveSoundHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveEffectHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveUnitPoolHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveItemPoolHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveQuestHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveQuestItemHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveDefeatConditionHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTimerDialogHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveLeaderboardHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveMultiboardHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveMultiboardItemHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTrackableHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveDialogHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveButtonHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveTextTagHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveLightningHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveImageHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveUbersplatHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveRegionHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveFogStateHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveFogModifierHandle",
new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveAgentHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("SaveHashtableHandle", new SaveHashtableValueFunc());
jassProgramVisitor.getJassNativeManager().createNative("LoadInteger",
new LoadHashtableValueFunc(IntegerJassValue.ZERO));
jassProgramVisitor.getJassNativeManager().createNative("LoadReal",
new LoadHashtableValueFunc(RealJassValue.ZERO));
jassProgramVisitor.getJassNativeManager().createNative("LoadBoolean",
new LoadHashtableValueFunc(BooleanJassValue.FALSE));
jassProgramVisitor.getJassNativeManager().createNative("LoadStr",
new LoadHashtableValueFunc(StringJassValue.EMPTY_STRING));
jassProgramVisitor.getJassNativeManager().createNative("HaveSavedInteger",
new HaveSavedHashtableValueFunc(JassType.INTEGER));
jassProgramVisitor.getJassNativeManager().createNative("HaveSavedReal",
new HaveSavedHashtableValueFunc(JassType.REAL));
jassProgramVisitor.getJassNativeManager().createNative("HaveSavedBoolean",
new HaveSavedHashtableValueFunc(JassType.BOOLEAN));
jassProgramVisitor.getJassNativeManager().createNative("HaveSavedStr",
new HaveSavedHashtableValueFunc(JassType.STRING));
jassProgramVisitor.getJassNativeManager().createNative("GetExpiredTimer", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
return new HandleJassValue(timerType,
((CommonTriggerExecutionScope) triggerScope).getExpiringTimer());
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerStructureCount", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CPlayer whichPlayer = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final boolean includeIncomplete = arguments.get(1).visit(BooleanJassValueVisitor.getInstance());
final List<CUnit> units = simulation.getUnits();
int count = 0;
for (final CUnit unit : units) {
if (unit.getPlayerIndex() == whichPlayer.getId()) {
if (includeIncomplete || !unit.isConstructing()) {
count++;
}
}
}
return new IntegerJassValue(count);
}
});
jassProgramVisitor.getJassNativeManager().createNative("GetPlayerTypedUnitCount", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CPlayer whichPlayer = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final String legacySystemUnitTypeName = arguments.get(1)
.visit(StringJassValueVisitor.getInstance());
final boolean includeIncomplete = arguments.get(2).visit(BooleanJassValueVisitor.getInstance());
final boolean includeUpgrades = arguments.get(3).visit(BooleanJassValueVisitor.getInstance());
final List<CUnit> units = simulation.getUnits();
int count = 0;
// TODO includeUpgrades is NYI!!
for (final CUnit unit : units) {
if (unit.getPlayerIndex() == whichPlayer.getId()) {
if (legacySystemUnitTypeName.equals(unit.getUnitType().getLegacyName())) {
if (includeIncomplete || !unit.isConstructing()) {
count++;
}
}
}
}
return new IntegerJassValue(count);
}
});
jassProgramVisitor.getJassNativeManager().createNative("IsUnitEnemy", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final CPlayer whichPlayer = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
if ((whichUnit == null) || (whichPlayer == null)) {
return BooleanJassValue.FALSE;
}
return BooleanJassValue
.of(!whichPlayer.hasAlliance(whichUnit.getPlayerIndex(), CAllianceType.PASSIVE));
}
});
jassProgramVisitor.getJassNativeManager().createNative("IsUnitAlly", new JassFunction() {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CUnit whichUnit = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final CPlayer whichPlayer = arguments.get(1).visit(ObjectJassValueVisitor.getInstance());
if ((whichUnit == null) || (whichPlayer == null)) {
return BooleanJassValue.FALSE;
}
return BooleanJassValue
.of(whichPlayer.hasAlliance(whichUnit.getPlayerIndex(), CAllianceType.PASSIVE));
}
});
}
private void registerConfigNatives(final JassProgramVisitor jassProgramVisitor, final War3MapConfig mapConfig,
@ -4169,9 +4405,26 @@ public class Jass2 {
});
}
public void config() {
try {
this.jassProgramVisitor.getGlobals().getFunctionByName("config").call(Collections.emptyList(),
this.jassProgramVisitor.getGlobals(), JassProgramVisitor.EMPTY_TRIGGER_SCOPE);
}
catch (final Exception exc) {
throw new JassException(this.jassProgramVisitor.getGlobals(),
"Exception on Line " + this.jassProgramVisitor.getGlobals().getLineNumber(), exc);
}
}
public void main() {
this.jassProgramVisitor.getGlobals().getFunctionByName("main").call(Collections.emptyList(),
new GlobalScope(), null);
try {
this.jassProgramVisitor.getGlobals().getFunctionByName("main").call(Collections.emptyList(),
this.jassProgramVisitor.getGlobals(), JassProgramVisitor.EMPTY_TRIGGER_SCOPE);
}
catch (final Exception exc) {
throw new JassException(this.jassProgramVisitor.getGlobals(),
"Exception on Line " + this.jassProgramVisitor.getGlobals().getLineNumber(), exc);
}
}
}
@ -4286,8 +4539,9 @@ public class Jass2 {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final String funcName = arguments.get(0).visit(ObjectJassValueVisitor.<String>getInstance());
final String funcName = arguments.get(0).visit(StringJassValueVisitor.getInstance());
final JassFunction functionByName = globalScope.getFunctionByName(funcName);
System.out.println("ExecuteFunc (\"" + funcName + "\")");
if (functionByName != null) {
// TODO below TriggerExecutionScope.EMPTY is probably not correct
functionByName.call(Collections.emptyList(), globalScope, TriggerExecutionScope.EMPTY);
@ -4476,4 +4730,64 @@ public class Jass2 {
e.printStackTrace();
}
}
private static final class SaveHashtableValueFunc implements JassFunction {
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CHashtable table = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final Integer parentKey = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final Integer childKey = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
table.save(parentKey, childKey, arguments.get(3));
return null;
}
}
private static final class LoadHashtableValueFunc implements JassFunction {
private final JassValue nullValue;
public LoadHashtableValueFunc(final JassValue nullValue) {
this.nullValue = nullValue;
}
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CHashtable table = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final Integer parentKey = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final Integer childKey = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
final Object loadedValue = table.load(parentKey, childKey);
if (loadedValue == null) {
return this.nullValue;
}
return (JassValue) loadedValue;
}
}
private static final class HaveSavedHashtableValueFunc implements JassFunction {
private final JassType jassType;
public HaveSavedHashtableValueFunc(final JassType jassType) {
this.jassType = jassType;
}
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
final CHashtable table = arguments.get(0).visit(ObjectJassValueVisitor.getInstance());
final Integer parentKey = arguments.get(1).visit(IntegerJassValueVisitor.getInstance());
final Integer childKey = arguments.get(2).visit(IntegerJassValueVisitor.getInstance());
final Object loadedValue = table.load(parentKey, childKey);
if (loadedValue != null) {
if (loadedValue instanceof JassValue) {
final JassValue loadedJassValue = (JassValue) loadedValue;
final JassType type = loadedJassValue.visit(JassTypeGettingValueVisitor.getInstance());
if (this.jassType.isAssignableFrom(type)) {
return BooleanJassValue.TRUE;
}
}
}
return BooleanJassValue.FALSE;
}
}
}

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.parsers.jass.triggers;
import java.util.Collections;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
@ -18,8 +19,14 @@ public class BoolExprCondition implements TriggerBooleanExpression {
@Override
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
final JassValue booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST,
globalScope, triggerScope);
final JassValue booleanJassReturnValue;
try {
booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST, globalScope,
triggerScope);
}
catch (final Exception e) {
throw new JassException(globalScope, "Exception during BoolExprCondition.evaluate()", e);
}
final Boolean booleanReturnValue = booleanJassReturnValue.visit(BooleanJassValueVisitor.getInstance());
return booleanReturnValue.booleanValue();
}

View File

@ -2,6 +2,7 @@ package com.etheller.warsmash.parsers.jass.triggers;
import java.util.Collections;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
@ -18,8 +19,14 @@ public class BoolExprFilter implements TriggerBooleanExpression {
@Override
public boolean evaluate(final GlobalScope globalScope, final TriggerExecutionScope triggerScope) {
final JassValue booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST,
globalScope, triggerScope);
final JassValue booleanJassReturnValue;
try {
booleanJassReturnValue = this.takesNothingReturnsBooleanFunction.call(Collections.EMPTY_LIST, globalScope,
triggerScope);
}
catch (final Exception e) {
throw new JassException(globalScope, "Exception during BoolExprFilter.evaluate()", e);
}
final Boolean booleanReturnValue = booleanJassReturnValue.visit(BooleanJassValueVisitor.getInstance());
return booleanReturnValue.booleanValue();
}

View File

@ -1,6 +1,7 @@
package com.etheller.warsmash.parsers.w3x.w3i;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.etheller.warsmash.util.ParseUtils;
@ -12,7 +13,7 @@ public class RandomUnitTable {
private String name;
private int positions;
private int[] columnTypes;
private List<RandomUnit> units;
private final List<RandomUnit> units = new ArrayList<>();
public void load(final LittleEndianDataInputStream stream) throws IOException {
this.id = stream.readInt(); // TODO is this a War3ID?

View File

@ -25,7 +25,7 @@ public class WarsmashConstants {
// find it yet so I used this
public static final String DEFAULT_STRING = "Default string";
public static final boolean CATCH_CURSOR = true;
public static final boolean CATCH_CURSOR = false;
public static final boolean VERBOSE_LOGGING = true;
public static final boolean ENABLE_DEBUG = false;
public static final char SPECIAL_ESCAPE_KEYCODE = 0x7E;
@ -36,7 +36,7 @@ public class WarsmashConstants {
// workaround to fix it if you need the local files
// to take priority over built-ins for tilesets.
public static final boolean FIX_FLAT_FILES_TILESET_LOADING = false;
public static final boolean ENABLE_MUSIC = false;
public static final boolean ENABLE_MUSIC = true;
public static final boolean LOAD_UNITS_FROM_WORLDEDIT_DATA = false;
public static final boolean LOCAL_TEMP_TEST_ALL_PLAYERS_PLAYING = true;
}

View File

@ -205,7 +205,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
public DataTable uiSoundsTable;
private MdxComplexInstance confirmationInstance;
public MdxComplexInstance dncUnit;
public MdxComplexInstance dncUnitDay;
public MdxComplexInstance dncTerrain;
public MdxComplexInstance dncTarget;
public CSimulation simulation;
@ -1618,17 +1617,22 @@ public class War3MapViewer extends AbstractMdxModelViewer {
break;
}
}
this.dncTerrain.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncTerrain.update(rawDeltaTime, null);
this.dncUnit.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncUnit.update(rawDeltaTime, null);
this.dncUnitDay.setFrameByRatio(0.5f);
this.dncUnitDay.update(rawDeltaTime, null);
this.dncTarget.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncTarget.update(rawDeltaTime, null);
if (this.dncTerrain != null) {
this.dncTerrain.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncTerrain.update(rawDeltaTime, null);
}
if (this.dncUnit != null) {
this.dncUnit.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncUnit.update(rawDeltaTime, null);
}
if (this.dncTarget != null) {
this.dncTarget.setFrameByRatio(
this.simulation.getGameTimeOfDay() / this.simulation.getGameplayConstants().getGameDayHours());
this.dncTarget.update(rawDeltaTime, null);
}
}
}
@ -2095,9 +2099,6 @@ public class War3MapViewer extends AbstractMdxModelViewer {
this.dncUnit = (MdxComplexInstance) unitDNCModel.addInstance();
this.dncUnit.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
this.dncUnit.setSequence(0);
this.dncUnitDay = (MdxComplexInstance) unitDNCModel.addInstance();
this.dncUnitDay.setSequenceLoopMode(SequenceLoopMode.ALWAYS_LOOP);
this.dncUnitDay.setSequence(0);
final MdxModel targetDNCModel = (MdxModel) load(
mdx("Environment\\DNC\\DNCLordaeron\\DNCLordaeronTarget\\DNCLordaeronTarget.mdl"), PathSolver.DEFAULT,
null);

View File

@ -105,6 +105,7 @@ public class RenderDestructable extends RenderDoodad implements RenderWidget {
else if (!dead) {
if (this.dead) {
this.unitAnimationListenerImpl.playAnimation(true, PrimaryTag.BIRTH, SequenceUtils.EMPTY, 1.0f, true);
this.unitAnimationListenerImpl.queueAnimation(PrimaryTag.STAND, SequenceUtils.EMPTY, true);
// TODO add back shadow here
}

View File

@ -118,11 +118,13 @@ public class CSimulation implements CPlayerAPI {
for (int i = 0; i < WarsmashConstants.MAX_PLAYERS; i++) {
final CBasePlayer configPlayer = config.getPlayer(i);
final War3MapConfigStartLoc startLoc = config.getStartLoc(configPlayer.getStartLocationIndex());
final CRace defaultRace = CRace.UNDEAD;
final CRace defaultRace = CRace.ORC;
final CPlayer newPlayer = new CPlayer(defaultRace, new float[] { startLoc.getX(), startLoc.getY() },
configPlayer);
if (WarsmashConstants.LOCAL_TEMP_TEST_ALL_PLAYERS_PLAYING) {
newPlayer.setSlotState(CPlayerSlotState.PLAYING);
if (i < config.getPlayerCount()) {
newPlayer.setSlotState(CPlayerSlotState.PLAYING);
}
}
this.players.add(newPlayer);
}
@ -606,4 +608,11 @@ public class CSimulation implements CPlayerAPI {
public boolean isNight() {
return !this.daytime;
}
public void updateIsPlaying(final War3MapConfig mapConfig) {
for (int i = 0; i < mapConfig.getPlayerCount(); i++) {
this.players.get(i).setSlotState(CPlayerSlotState.PLAYING);
}
}
}

View File

@ -9,6 +9,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.interpreter.ast.util.CHandle;
import com.etheller.warsmash.parsers.jass.scope.CommonTriggerExecutionScope;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting.AbilityTarget;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CAttackType;
@ -16,7 +17,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat.CTargetType;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.JassGameEventsWar3;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit.CWidgetEvent;
public abstract class CWidget implements AbilityTarget {
public abstract class CWidget implements AbilityTarget, CHandle {
protected static final Rectangle tempRect = new Rectangle();
private final int handleId;
private float x;
@ -32,6 +33,7 @@ public abstract class CWidget implements AbilityTarget {
this.life = life;
}
@Override
public int getHandleId() {
return this.handleId;
}

View File

@ -1,5 +1,6 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
import com.etheller.interpreter.ast.util.CHandle;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CSimulation;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CUnit;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.CWidget;
@ -7,7 +8,7 @@ import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.targeting
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityActivationReceiver;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.util.AbilityTargetCheckReceiver;
public interface CAbilityView {
public interface CAbilityView extends CHandle {
void checkCanUse(CSimulation game, CUnit unit, int orderId, AbilityActivationReceiver receiver);
void checkCanTarget(CSimulation game, CUnit unit, int orderId, CWidget target,

View File

@ -0,0 +1,140 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities;
import com.etheller.warsmash.util.War3ID;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityBuildInProgress;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityHumanBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNagaBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNeutralBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityNightElfBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityOrcBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.build.CAbilityUndeadBuild;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.combat.CAbilityColdArrows;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericNoIconAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.generic.GenericSingleIconActiveAbility;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.hero.CAbilityHero;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityQueue;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityRally;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.queue.CAbilityReviveHero;
import com.etheller.warsmash.viewer5.handlers.w3x.simulation.abilities.upgrade.CAbilityUpgrade;
public class GetAbilityByRawcodeVisitor implements CAbilityVisitor<CAbility> {
private static final GetAbilityByRawcodeVisitor INSTANCE = new GetAbilityByRawcodeVisitor();
public static GetAbilityByRawcodeVisitor getInstance() {
return INSTANCE;
}
private static final War3ID RALLY_RAWCODE = War3ID.fromString("Aral");
private War3ID rawcode;
public GetAbilityByRawcodeVisitor reset(final War3ID rawcode) {
this.rawcode = rawcode;
return this;
}
@Override
public CAbility accept(final CAbilityAttack ability) {
return null;
}
@Override
public CAbility accept(final CAbilityMove ability) {
return null;
}
@Override
public CAbility accept(final CAbilityOrcBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityHumanBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityUndeadBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityNightElfBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityGeneric ability) {
if (this.rawcode.equals(ability.getRawcode())) {
return ability;
}
return null;
}
@Override
public CAbility accept(final CAbilityColdArrows ability) {
if (this.rawcode.equals(ability.getRawcode())) {
return ability;
}
return null;
}
@Override
public CAbility accept(final CAbilityNagaBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityNeutralBuild ability) {
return null;
}
@Override
public CAbility accept(final CAbilityBuildInProgress ability) {
return null;
}
@Override
public CAbility accept(final CAbilityQueue ability) {
return null;
}
@Override
public CAbility accept(final CAbilityUpgrade ability) {
return null;
}
@Override
public CAbility accept(final CAbilityReviveHero ability) {
return null;
}
@Override
public CAbility accept(final GenericSingleIconActiveAbility ability) {
if (this.rawcode.equals(ability.getAlias())) {
return ability;
}
return null;
}
@Override
public CAbility accept(final CAbilityRally ability) {
if (this.rawcode.equals(RALLY_RAWCODE)) {
return ability;
}
return null;
}
@Override
public CAbility accept(final GenericNoIconAbility ability) {
if (this.rawcode.equals(ability.getAlias())) {
return ability;
}
return null;
}
@Override
public CAbility accept(final CAbilityHero ability) {
return null;
}
}

View File

@ -1,9 +1,16 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.ai;
public enum AIDifficulty {
import com.etheller.interpreter.ast.util.CHandle;
public enum AIDifficulty implements CHandle {
NEWBIE,
NORMAL,
INSANE;
public static AIDifficulty[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.combat;
public enum CAttackType implements CodeKeyType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CAttackType implements CodeKeyType, CHandle {
UNKNOWN,
NORMAL,
PIERCE,
@ -43,4 +45,9 @@ public enum CAttackType implements CodeKeyType {
}
return valueOf(upperCaseAttackType);
}
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.item;
public enum CItemTypeJass {
import com.etheller.interpreter.ast.util.CHandle;
public enum CItemTypeJass implements CHandle {
PERMANENT,
CHARGED,
POWERUP,
@ -12,4 +14,9 @@ public enum CItemTypeJass {
ANY;
public static CItemTypeJass[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CAllianceType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CAllianceType implements CHandle {
PASSIVE,
HELP_REQUEST,
HELP_RESPONSE,
@ -13,4 +15,9 @@ public enum CAllianceType {
SHARED_VISION_FORCED;
public static CAllianceType[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CMapControl {
import com.etheller.interpreter.ast.util.CHandle;
public enum CMapControl implements CHandle {
USER,
COMPUTER,
RESCUABLE,
@ -9,4 +11,9 @@ public enum CMapControl {
NONE;
public static CMapControl[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CMapFlag {
import com.etheller.interpreter.ast.util.CHandle;
public enum CMapFlag implements CHandle {
MAP_FOG_HIDE_TERRAIN,
MAP_FOG_MAP_EXPLORED,
MAP_FOG_ALWAYS_VISIBLE,
@ -41,4 +43,9 @@ public enum CMapFlag {
public int getId() {
return 1 << ordinal();
}
@Override
public int getHandleId() {
return getId();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CMapPlacement {
import com.etheller.interpreter.ast.util.CHandle;
public enum CMapPlacement implements CHandle {
RANDOM,
FIXED,
USE_MAP_SETTINGS,
TEAMS_TOGETHER;
public static CMapPlacement[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -54,6 +54,7 @@ public class CPlayer extends CBasePlayer {
// which fields shouldn't be persisted if we do game state save later
private transient CPlayerStateNotifier stateNotifier = new CPlayerStateNotifier();
private float handicapXP;
private float handicap = 0.9f;
public CPlayer(final CRace race, final float[] startLocation, final CBasePlayer configPlayer) {
super(configPlayer);
@ -410,4 +411,12 @@ public class CPlayer extends CBasePlayer {
public float getHandicapXP() {
return this.handicapXP;
}
public void setHandicap(final float handicap) {
this.handicap = handicap;
}
public float getHandicap() {
return this.handicap;
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerColor {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPlayerColor implements CHandle {
RED,
BLUE,
CYAN,
@ -22,4 +24,9 @@ public enum CPlayerColor {
}
return null;
}
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerGameResult {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPlayerGameResult implements CHandle {
VICTORY,
DEFEAT,
TIE,
NEUTRAL;
public static CPlayerGameResult[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerScore {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPlayerScore implements CHandle {
UNITS_TRAINED,
UNITS_KILLED,
STRUCT_BUILT,
@ -28,4 +30,9 @@ public enum CPlayerScore {
TOTAL;
public static CPlayerScore[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CPlayerState {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPlayerState implements CHandle {
GAME_RESULT,
// current resource levels
//
@ -40,4 +42,9 @@ public enum CPlayerState {
NO_CREEP_SLEEP;
public static CPlayerState[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CRace {
import com.etheller.interpreter.ast.util.CHandle;
public enum CRace implements CHandle {
HUMAN(1),
ORC(2),
UNDEAD(3),
@ -29,4 +31,9 @@ public enum CRace {
}
return null;
}
@Override
public int getHandleId() {
return getId();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CRacePreference {
import com.etheller.interpreter.ast.util.CHandle;
public enum CRacePreference implements CHandle {
HUMAN,
ORC,
NIGHTELF,
@ -23,4 +25,9 @@ public enum CRacePreference {
public int getId() {
return 1 << ordinal();
}
@Override
public int getHandleId() {
return getId();
}
}

View File

@ -1,9 +1,16 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.players;
public enum CStartLocPrio {
import com.etheller.interpreter.ast.util.CHandle;
public enum CStartLocPrio implements CHandle {
LOW,
HIGH,
NOT;
public static CStartLocPrio[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -20,7 +20,7 @@ public class CRegionTriggerLeave {
}
public void fire(final CUnit unit, final CRegion region) {
if (this.filter.evaluate(this.globalScope,
if ((this.filter == null) || this.filter.evaluate(this.globalScope,
CommonTriggerExecutionScope.filterScope(TriggerExecutionScope.EMPTY, unit))) {
final CommonTriggerExecutionScope eventScope = CommonTriggerExecutionScope
.unitLeaveRegionScope(this.trigger, TriggerExecutionScope.EMPTY, unit, region);

View File

@ -1,9 +1,16 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.state;
public enum CGameState {
import com.etheller.interpreter.ast.util.CHandle;
public enum CGameState implements CHandle {
DIVINE_INTERVENTION,
DISCONNECTED,
TIME_OF_DAY;
public static CGameState[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.state;
public enum CUnitState {
import com.etheller.interpreter.ast.util.CHandle;
public enum CUnitState implements CHandle {
LIFE,
MAX_LIFE,
MANA,
MAX_MANA;
public static CUnitState[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
@ -25,7 +26,12 @@ public class CTimerJass extends CTimer {
@Override
public void onFire() {
final CommonTriggerExecutionScope handlerScope = CommonTriggerExecutionScope.expiringTimer(null, this);
this.handlerFunc.call(Collections.emptyList(), this.jassGlobalScope, handlerScope);
try {
this.handlerFunc.call(Collections.emptyList(), this.jassGlobalScope, handlerScope);
}
catch (final Exception e) {
throw new JassException(this.jassGlobalScope, "Exception during jass time fire", e);
}
for (final Trigger trigger : this.eventTriggers) {
final CommonTriggerExecutionScope executionScope = CommonTriggerExecutionScope.expiringTimer(trigger, this);
if (trigger.evaluate(this.jassGlobalScope, executionScope)) {

View File

@ -1,5 +1,7 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger;
import com.etheller.interpreter.ast.util.CHandle;
//===================================================
//Game, Player and Unit Events
//
@ -15,7 +17,7 @@ package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger;
//
//===================================================
public enum JassGameEventsWar3 {
public enum JassGameEventsWar3 implements CHandle {
// ===================================================
// For use with TriggerRegisterGameEvent
// ===================================================
@ -245,4 +247,9 @@ public enum JassGameEventsWar3 {
}
return ordinal;
}
@Override
public int getHandleId() {
return getEventId();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CBlendMode {
import com.etheller.interpreter.ast.util.CHandle;
public enum CBlendMode implements CHandle {
NONE,
KEYALPHA,
BLEND,
@ -9,4 +11,9 @@ public enum CBlendMode {
MODULATE_2X;
public static CBlendMode[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CCameraField {
import com.etheller.interpreter.ast.util.CHandle;
public enum CCameraField implements CHandle {
TARGET_DISTANCE,
FARZ,
ANGLE_OF_ATTACK,
@ -10,4 +12,9 @@ public enum CCameraField {
ZOFFSET;
public static CCameraField[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CDamageType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CDamageType implements CHandle {
UNKNOWN,
UNKNOWN_CODE_1,
UNKNOWN_CODE_2,
@ -30,4 +32,9 @@ public enum CDamageType {
UNIVERSAL;
public static CDamageType[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CEffectType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CEffectType implements CHandle {
EFFECT,
TARGET,
CASTER,
@ -10,4 +12,9 @@ public enum CEffectType {
LIGHTNING;
public static CEffectType[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CFogState {
import com.etheller.interpreter.ast.util.CHandle;
public enum CFogState implements CHandle {
MASKED,
FOGGED,
VISIBLE;
@ -19,4 +21,9 @@ public enum CFogState {
public int getId() {
return 1 << ordinal();
}
@Override
public int getHandleId() {
return getId();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CGameSpeed {
import com.etheller.interpreter.ast.util.CHandle;
public enum CGameSpeed implements CHandle {
SLOWEST,
SLOW,
NORMAL,
@ -8,4 +10,9 @@ public enum CGameSpeed {
FASTEST;
public static CGameSpeed[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CGameType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CGameType implements CHandle {
MELEE,
FFA,
USE_MAP_SETTINGS,
@ -24,4 +26,9 @@ public enum CGameType {
public int getId() {
return 1 << ordinal();
}
@Override
public int getHandleId() {
return getId();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CMapDensity {
import com.etheller.interpreter.ast.util.CHandle;
public enum CMapDensity implements CHandle {
NONE,
LIGHT,
MEDIUM,
HEAVY;
public static CMapDensity[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CMapDifficulty {
import com.etheller.interpreter.ast.util.CHandle;
public enum CMapDifficulty implements CHandle {
EASY,
NORMAL,
HARD,
INSANE;
public static CMapDifficulty[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CPathingTypeJass {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPathingTypeJass implements CHandle {
ANY,
WALKABILITY,
FLYABILITY,
@ -11,4 +13,9 @@ public enum CPathingTypeJass {
AMPHIBIOUSPATHING;
public static CPathingTypeJass[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,9 +1,16 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CPlayerSlotState {
import com.etheller.interpreter.ast.util.CHandle;
public enum CPlayerSlotState implements CHandle {
EMPTY,
PLAYING,
LEFT;
public static CPlayerSlotState[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,8 +1,15 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CRarityControl {
import com.etheller.interpreter.ast.util.CHandle;
public enum CRarityControl implements CHandle {
FREQUENT,
RARE;
public static CRarityControl[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,8 +1,15 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CSoundType {
import com.etheller.interpreter.ast.util.CHandle;
public enum CSoundType implements CHandle {
EFFECT,
EFFECT_LOOPED;
public static CSoundType[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CSoundVolumeGroup {
import com.etheller.interpreter.ast.util.CHandle;
public enum CSoundVolumeGroup implements CHandle {
UNITMOVEMENT,
UNITSOUNDS,
COMBAT,
@ -11,4 +13,9 @@ public enum CSoundVolumeGroup {
FIRE;
public static CSoundVolumeGroup[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,10 +1,17 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CTexMapFlags {
import com.etheller.interpreter.ast.util.CHandle;
public enum CTexMapFlags implements CHandle {
NONE,
WRAP_U,
WRAP_V,
WRAP_UV;
public static CTexMapFlags[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,8 +1,15 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CVersion {
import com.etheller.interpreter.ast.util.CHandle;
public enum CVersion implements CHandle {
REIGN_OF_CHAOS,
FROZEN_THRONE;
public static CVersion[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.trigger.enumtypes;
public enum CWeaponSoundTypeJass {
import com.etheller.interpreter.ast.util.CHandle;
public enum CWeaponSoundTypeJass implements CHandle {
WHOKNOWS(null),
METAL_LIGHT_CHOP("MetalLightChop"),
METAL_MEDIUM_CHOP("MetalMediumChop"),
@ -37,4 +39,9 @@ public enum CWeaponSoundTypeJass {
}
public static CWeaponSoundTypeJass[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.unit;
public enum CUnitTypeJass {
import com.etheller.interpreter.ast.util.CHandle;
public enum CUnitTypeJass implements CHandle {
HERO,
DEAD,
STRUCTURE,
@ -36,4 +38,9 @@ public enum CUnitTypeJass {
MAGIC_IMMUNE;
public static CUnitTypeJass[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -0,0 +1,30 @@
package com.etheller.warsmash.viewer5.handlers.w3x.simulation.util;
import java.util.HashMap;
import java.util.Map;
public class CHashtable {
private final Map<Integer, Map<Integer, Object>> parentKeyToChildTable = new HashMap<>();
public void save(final Integer parentKey, final Integer childKey, final Object object) {
Map<Integer, Object> childTable = this.parentKeyToChildTable.get(parentKey);
if (childTable == null) {
childTable = new HashMap<>();
this.parentKeyToChildTable.put(parentKey, childTable);
}
if (object == null) {
childTable.remove(childKey);
}
else {
childTable.put(childKey, object);
}
}
public Object load(final Integer parentKey, final Integer childKey) {
final Map<Integer, Object> childTable = this.parentKeyToChildTable.get(parentKey);
if (childTable != null) {
return childTable.get(childKey);
}
return null;
}
}

View File

@ -354,6 +354,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
private boolean currentMusicRandomizeIndex;
private final List<CTimerDialog> timerDialogs = new ArrayList<>();
private final AnyClickableUnitFilter anyClickableUnitFilter;
private final AnyTargetableUnitFilter anyTargetableUnitFilter;
public MeleeUI(final DataSource dataSource, final ExtendViewport uiViewport, final Scene uiScene,
final Scene portraitScene, final CameraPreset[] cameraPresets, final CameraRates cameraRates,
@ -388,6 +389,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
this.itemCommandCardCommandListener = new ItemCommandCardCommandListener();
this.anyClickableUnitFilter = new AnyClickableUnitFilter();
this.anyTargetableUnitFilter = new AnyTargetableUnitFilter();
}
private MeleeUIMinimap createMinimap(final War3MapViewer war3MapViewer) {
@ -1644,6 +1646,13 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
}
}
private final class AnyTargetableUnitFilter implements CWidgetFilterFunction {
@Override
public boolean call(final CWidget unit) {
return !unit.isDead();
}
}
private final class CursorTargetSetupVisitor implements CAbilityVisitor<Void> {
private int baseMouseX;
private int baseMouseY;
@ -3013,9 +3022,13 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma
if (button == Input.Buttons.RIGHT) {
if ((getSelectedUnit() != null) && (getSelectedUnit().getSimulationUnit()
.getPlayerIndex() == this.war3MapViewer.getLocalPlayerIndex())) {
final RenderWidget rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY,
RenderWidget rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY,
this.anyClickableUnitFilter);
if ((rayPickUnit != null) && !rayPickUnit.getSimulationWidget().isDead()) {
if (rayPickUnit == null) {
rayPickUnit = this.war3MapViewer.rayPickUnit(screenX, worldScreenY,
this.anyTargetableUnitFilter);
}
if (rayPickUnit != null) {
boolean ordered = false;
boolean rallied = false;
boolean attacked = false;

View File

@ -657,8 +657,8 @@ public class MenuUI {
else {
turnManager = GameTurnManager.LOCAL;
}
final War3MapViewer viewer = new War3MapViewer(codebase, this.screenManager,
new War3MapConfig(WarsmashConstants.MAX_PLAYERS), turnManager);
final War3MapConfig mapConfig = new War3MapConfig(WarsmashConstants.MAX_PLAYERS);
final War3MapViewer viewer = new War3MapViewer(codebase, this.screenManager, mapConfig, turnManager);
if (WarsmashGdxMapScreen.ENABLE_AUDIO) {
viewer.worldScene.enableAudio();

View File

@ -98,6 +98,8 @@ baseExpression:
|
INTEGER #IntegerLiteralExpression
|
HEX_CONSTANT #HexIntegerLiteralExpression
|
RAWCODE #RawcodeLiteralExpression
|
REAL #RealLiteralExpression
@ -199,7 +201,7 @@ block:
;
functionBlock:
FUNCTION ID TAKES paramList RETURNS type newlines statements ENDFUNCTION newlines
CONSTANT? FUNCTION ID TAKES paramList RETURNS type newlines statements ENDFUNCTION newlines
;
statements:
@ -259,14 +261,17 @@ LOOP : 'loop';
ENDLOOP : 'endloop';
EXITWHEN : 'exitwhen';
STRING_LITERAL : ('"'.*?'"');
fragment ESCAPED_QUOTE : '\\"';
STRING_LITERAL : '"' ( ESCAPED_QUOTE | ~('\n'|'\r') )*? '"';
INTEGER : [0]|([1-9][0-9]*) ;
HEX_CONSTANT : '0x'(([0-9]|[a-f])*) ;
RAWCODE : ('\''.*?'\'');
REAL : (([0]|([1-9][0-9]*))'.'[0-9]*)|('.'([0]|([1-9][0-9]*))) ;
REAL : (([0]|([1-9][0-9]*))'.'[0-9]*)|('.'([0-9]*)) ;
NULL : 'null' ;
TRUE : 'true' ;

View File

@ -0,0 +1,34 @@
package com.etheller.interpreter.ast.debug;
import java.util.List;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
public class DebuggingJassFunction implements JassFunction {
private final int lineNo;
private final String sourceFile;
private final String functionName;
private final JassFunction delegate;
public DebuggingJassFunction(final int lineNo, final String sourceFile, final String functionName,
final JassFunction delegate) {
this.lineNo = lineNo;
this.sourceFile = sourceFile;
this.functionName = functionName;
this.delegate = delegate;
}
@Override
public JassValue call(final List<JassValue> arguments, final GlobalScope globalScope,
final TriggerExecutionScope triggerScope) {
globalScope.pushJassStack(new JassStackElement(this.sourceFile, this.functionName, this.lineNo));
globalScope.setLineNumber(this.lineNo);
final JassValue returnValue = this.delegate.call(arguments, globalScope, triggerScope);
globalScope.popJassStack();
return returnValue;
}
}

View File

@ -0,0 +1,25 @@
package com.etheller.interpreter.ast.debug;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.LocalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.statement.JassStatement;
import com.etheller.interpreter.ast.value.JassValue;
public class DebuggingJassStatement implements JassStatement {
private final int lineNo;
private final JassStatement delegate;
public DebuggingJassStatement(final int lineNo, final JassStatement delegate) {
this.lineNo = lineNo;
this.delegate = delegate;
}
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
return this.delegate.execute(globalScope, localScope, triggerScope);
}
}

View File

@ -0,0 +1,22 @@
package com.etheller.interpreter.ast.debug;
import java.util.List;
import com.etheller.interpreter.ast.scope.GlobalScope;
public class JassException extends RuntimeException {
public JassException(final GlobalScope globalScope, final String message, final Exception javaCause) {
super(message(globalScope, message), javaCause);
}
private static String message(final GlobalScope globalScope, final String message) {
final List<JassStackElement> stackTrace = globalScope.copyJassStack();
final StringBuilder sb = new StringBuilder(message);
for (final JassStackElement element : stackTrace) {
sb.append("\n");
sb.append(element);
}
return sb.toString();
}
}

View File

@ -0,0 +1,38 @@
package com.etheller.interpreter.ast.debug;
public class JassStackElement {
private final String sourceFile;
private final String functionName;
private int lineNumber;
public JassStackElement(final String sourceFile, final String functionName, final int lineNumber) {
this.sourceFile = sourceFile;
this.functionName = functionName;
this.lineNumber = lineNumber;
}
public JassStackElement(final JassStackElement other) {
this(other.sourceFile, other.functionName, other.lineNumber);
}
public String getSourceFile() {
return this.sourceFile;
}
public String getFunctionName() {
return this.functionName;
}
public int getLineNumber() {
return this.lineNumber;
}
public void setLineNumber(final int lineNumber) {
this.lineNumber = lineNumber;
}
@Override
public String toString() {
return "\tat " + this.functionName + "(" + this.sourceFile + ":" + +this.lineNumber + ")";
}
}

View File

@ -283,17 +283,17 @@ public enum ArithmeticSigns implements ArithmeticSign {
@Override
public BooleanJassValue apply(final String left, final String right) {
return BooleanJassValue.of(equals(left, right));
return BooleanJassValue.of(isEqual(left, right));
}
@Override
public BooleanJassValue apply(final HandleJassValue left, final HandleJassValue right) {
return BooleanJassValue.of(equals(left, right));
return BooleanJassValue.of(isEqual(left, right));
}
@Override
public BooleanJassValue apply(final CodeJassValue left, final CodeJassValue right) {
return BooleanJassValue.of(equals(left, right));
return BooleanJassValue.of(isEqual(left, right));
}
},
NOT_EQUALS() {
@ -324,17 +324,17 @@ public enum ArithmeticSigns implements ArithmeticSign {
@Override
public JassValue apply(final String left, final String right) {
return BooleanJassValue.of(!equals(left, right));
return BooleanJassValue.of(!isEqual(left, right));
}
@Override
public JassValue apply(final HandleJassValue left, final HandleJassValue right) {
return BooleanJassValue.of(!equals(left, right));
return BooleanJassValue.of(!isEqual(left, right));
}
@Override
public BooleanJassValue apply(final CodeJassValue left, final CodeJassValue right) {
return BooleanJassValue.of(!equals(left, right));
return BooleanJassValue.of(!isEqual(left, right));
}
},
LESS() {
@ -502,7 +502,7 @@ public enum ArithmeticSigns implements ArithmeticSign {
}
};
private static boolean equals(final String left, final String right) {
private static boolean isEqual(final String left, final String right) {
boolean equals;
if (left == null) {
if (right == null) {
@ -518,11 +518,11 @@ public enum ArithmeticSigns implements ArithmeticSign {
return equals;
}
private static boolean equals(final HandleJassValue left, final HandleJassValue right) {
private static boolean isEqual(final HandleJassValue left, final HandleJassValue right) {
return (left.getJavaValue() == right.getJavaValue()) && (left.getType() == right.getType());
}
private static boolean equals(final CodeJassValue left, final CodeJassValue right) {
private static boolean isEqual(final CodeJassValue left, final CodeJassValue right) {
return (left.getValue() == right.getValue());
}
}

View File

@ -35,6 +35,12 @@ public abstract class AbstractJassFunction implements JassFunction {
final JassParameter parameter = this.parameters.get(i);
final JassValue argument = arguments.get(i);
if (!parameter.matchesType(argument)) {
if ((parameter == null) || (argument == null)) {
System.err.println(
"Returning null because we called some Jass function with incorrect argument types, and the types were null!!!");
System.err.println("This is a temporary hack for tests and showcase programming solutions");
return null;
}
System.err.println(
parameter.getType() + " != " + argument.visit(JassTypeGettingValueVisitor.getInstance()));
throw new RuntimeException(

View File

@ -21,13 +21,14 @@ public class JassNativeManager {
this.nameToNativeCode.put(name, nativeCode);
}
public void registerNativeCode(final String name, final List<JassParameter> parameters, final JassType returnType,
final GlobalScope globals) {
public void registerNativeCode(final int lineNo, final String sourceFile, final String name,
final List<JassParameter> parameters, final JassType returnType, final GlobalScope globals) {
if (this.registeredNativeNames.contains(name)) {
throw new RuntimeException("Native already registered: " + name);
}
final JassFunction nativeCode = this.nameToNativeCode.remove(name);
globals.defineFunction(name, new NativeJassFunction(parameters, returnType, name, nativeCode));
globals.defineFunction(lineNo, sourceFile, name,
new NativeJassFunction(parameters, returnType, name, nativeCode));
this.registeredNativeNames.add(name);
}

View File

@ -1,14 +1,21 @@
package com.etheller.interpreter.ast.scope;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.etheller.interpreter.ast.Assignable;
import com.etheller.interpreter.ast.debug.DebuggingJassFunction;
import com.etheller.interpreter.ast.debug.JassStackElement;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.trigger.RemovableTriggerEvent;
import com.etheller.interpreter.ast.scope.trigger.Trigger;
import com.etheller.interpreter.ast.scope.variableevent.CLimitOp;
import com.etheller.interpreter.ast.scope.variableevent.VariableEvent;
import com.etheller.interpreter.ast.util.JassSettings;
import com.etheller.interpreter.ast.value.ArrayJassType;
import com.etheller.interpreter.ast.value.ArrayJassValue;
import com.etheller.interpreter.ast.value.HandleJassType;
@ -27,7 +34,7 @@ public final class GlobalScope {
public final HandleJassType handleType;
private static int lineNumber;
private final ArrayDeque<JassStackElement> jassStack = new ArrayDeque<>();
public GlobalScope() {
this.handleType = registerHandleType("handle");// the handle type
@ -39,12 +46,39 @@ public final class GlobalScope {
registerPrimitiveType(JassType.STRING);
}
public static void setLineNumber(final int lineNo) {
lineNumber = lineNo;
public Deque<JassStackElement> getJassStack() {
return this.jassStack;
}
public static int getLineNumber() {
return lineNumber;
public List<JassStackElement> copyJassStack() {
final List<JassStackElement> copiedStack = new ArrayList<>();
for (final JassStackElement stackElement : this.jassStack) {
copiedStack.add(new JassStackElement(stackElement));
}
return copiedStack;
}
public void pushJassStack(final JassStackElement element) {
this.jassStack.push(element);
}
public void popJassStack() {
this.jassStack.pop();
}
public void setLineNumber(final int lineNo) {
final JassStackElement top = this.jassStack.peekFirst();
if (top != null) {
top.setLineNumber(lineNo);
}
}
public int getLineNumber() {
final JassStackElement top = this.jassStack.peekFirst();
if (top != null) {
return top.getLineNumber();
}
return -1;
}
public HandleJassType registerHandleType(final String name) {
@ -101,8 +135,14 @@ public final class GlobalScope {
return this.globals.get(name);
}
public void defineFunction(final String name, final JassFunction function) {
this.functions.put(name, function);
public void defineFunction(final int lineNo, final String sourceFile, final String name,
final JassFunction function) {
if (JassSettings.DEBUG) {
this.functions.put(name, new DebuggingJassFunction(lineNo, sourceFile, name, function));
}
else {
this.functions.put(name, function);
}
}
public JassFunction getFunctionByName(final String name) {

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.etheller.interpreter.ast.debug.JassException;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
@ -60,7 +61,12 @@ public class Trigger {
return;
}
for (final JassFunction action : this.actions) {
action.call(Collections.emptyList(), globalScope, triggerScope);
try {
action.call(Collections.emptyList(), globalScope, triggerScope);
}
catch (final Exception e) {
throw new JassException(globalScope, "Exception during Trigger action execute", e);
}
}
}

View File

@ -1,6 +1,8 @@
package com.etheller.interpreter.ast.scope.variableevent;
public enum CLimitOp {
import com.etheller.interpreter.ast.util.CHandle;
public enum CLimitOp implements CHandle {
LESS_THAN,
LESS_THAN_OR_EQUAL,
EQUAL,
@ -9,4 +11,9 @@ public enum CLimitOp {
NOT_EQUAL;
public static CLimitOp[] VALUES = values();
@Override
public int getHandleId() {
return ordinal();
}
}

View File

@ -14,11 +14,9 @@ public class JassArrayedAssignmentStatement implements JassStatement {
private final String identifier;
private final JassExpression indexExpression;
private final JassExpression expression;
private final int lineNo;
public JassArrayedAssignmentStatement(final int lineNo, final String identifier,
final JassExpression indexExpression, final JassExpression expression) {
this.lineNo = lineNo;
public JassArrayedAssignmentStatement(final String identifier, final JassExpression indexExpression,
final JassExpression expression) {
this.identifier = identifier;
this.indexExpression = indexExpression;
this.expression = expression;
@ -27,7 +25,6 @@ public class JassArrayedAssignmentStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
Assignable variable = localScope.getAssignableLocal(this.identifier);
final JassValue index = this.indexExpression.evaluate(globalScope, localScope, triggerScope);
if (variable == null) {

View File

@ -11,12 +11,10 @@ import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
public class JassCallStatement implements JassStatement {
private final int lineNo;
private final String functionName;
private final List<JassExpression> arguments;
public JassCallStatement(final int lineNo, final String functionName, final List<JassExpression> arguments) {
this.lineNo = lineNo;
public JassCallStatement(final String functionName, final List<JassExpression> arguments) {
this.functionName = functionName;
this.arguments = arguments;
}
@ -24,7 +22,6 @@ public class JassCallStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
final JassFunction functionByName = globalScope.getFunctionByName(this.functionName);
if (functionByName == null) {
throw new RuntimeException("Undefined function: " + this.functionName);

View File

@ -10,18 +10,15 @@ import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
public class JassExitWhenStatement implements JassStatement {
public static final StringJassValue LOOP_EXIT_NOTICE = new StringJassValue("EXIT");
private final int lineNo;
private final JassExpression expression;
public JassExitWhenStatement(final int lineNo, final JassExpression expression) {
this.lineNo = lineNo;
public JassExitWhenStatement(final JassExpression expression) {
this.expression = expression;
}
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
if (this.expression.evaluate(globalScope, localScope, triggerScope)
.visit(BooleanJassValueVisitor.getInstance())) {
return LOOP_EXIT_NOTICE;

View File

@ -10,14 +10,12 @@ import com.etheller.interpreter.ast.value.JassValue;
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
public class JassIfElseIfStatement implements JassStatement {
private final int lineNo;
private final JassExpression condition;
private final List<JassStatement> thenStatements;
private final JassStatement elseifTail;
public JassIfElseIfStatement(final int lineNo, final JassExpression condition,
final List<JassStatement> thenStatements, final JassStatement elseifTail) {
this.lineNo = lineNo;
public JassIfElseIfStatement(final JassExpression condition, final List<JassStatement> thenStatements,
final JassStatement elseifTail) {
this.condition = condition;
this.thenStatements = thenStatements;
this.elseifTail = elseifTail;
@ -26,7 +24,6 @@ public class JassIfElseIfStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
if (this.condition.evaluate(globalScope, localScope, triggerScope)
.visit(BooleanJassValueVisitor.getInstance())) {
for (final JassStatement statement : this.thenStatements) {

View File

@ -10,14 +10,12 @@ import com.etheller.interpreter.ast.value.JassValue;
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
public class JassIfElseStatement implements JassStatement {
private final int lineNo;
private final JassExpression condition;
private final List<JassStatement> thenStatements;
private final List<JassStatement> elseStatements;
public JassIfElseStatement(final int lineNo, final JassExpression condition,
final List<JassStatement> thenStatements, final List<JassStatement> elseStatements) {
this.lineNo = lineNo;
public JassIfElseStatement(final JassExpression condition, final List<JassStatement> thenStatements,
final List<JassStatement> elseStatements) {
this.condition = condition;
this.thenStatements = thenStatements;
this.elseStatements = elseStatements;
@ -26,7 +24,6 @@ public class JassIfElseStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
if (this.condition.evaluate(globalScope, localScope, triggerScope)
.visit(BooleanJassValueVisitor.getInstance())) {
for (final JassStatement statement : this.thenStatements) {

View File

@ -10,12 +10,10 @@ import com.etheller.interpreter.ast.value.JassValue;
import com.etheller.interpreter.ast.value.visitor.BooleanJassValueVisitor;
public class JassIfStatement implements JassStatement {
private final int lineNo;
private final JassExpression condition;
private final List<JassStatement> thenStatements;
public JassIfStatement(final int lineNo, final JassExpression condition, final List<JassStatement> thenStatements) {
this.lineNo = lineNo;
public JassIfStatement(final JassExpression condition, final List<JassStatement> thenStatements) {
this.condition = condition;
this.thenStatements = thenStatements;
}
@ -31,7 +29,6 @@ public class JassIfStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
final JassValue evaluate = this.condition.evaluate(globalScope, localScope, triggerScope);
// TODO this null is here for simulations where we are missing natives, remove
// it on full release

View File

@ -10,12 +10,9 @@ import com.etheller.interpreter.ast.value.JassValue;
public class JassLocalDefinitionStatement implements JassStatement {
private final String identifier;
private final JassExpression expression;
private final int lineNo;
private final JassType type;
public JassLocalDefinitionStatement(final int lineNo, final String identifier, final JassType type,
final JassExpression expression) {
this.lineNo = lineNo;
public JassLocalDefinitionStatement(final String identifier, final JassType type, final JassExpression expression) {
this.identifier = identifier;
this.type = type;
this.expression = expression;
@ -24,7 +21,6 @@ public class JassLocalDefinitionStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
localScope.createLocal(this.identifier, this.type,
this.expression.evaluate(globalScope, localScope, triggerScope));
return null;

View File

@ -3,16 +3,15 @@ package com.etheller.interpreter.ast.statement;
import com.etheller.interpreter.ast.scope.GlobalScope;
import com.etheller.interpreter.ast.scope.LocalScope;
import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.IntegerJassValue;
import com.etheller.interpreter.ast.value.JassType;
import com.etheller.interpreter.ast.value.JassValue;
public class JassLocalStatement implements JassStatement {
private final String identifier;
private final int lineNo;
private final JassType type;
public JassLocalStatement(final int lineNo, final String identifier, final JassType type) {
this.lineNo = lineNo;
public JassLocalStatement(final String identifier, final JassType type) {
this.identifier = identifier;
this.type = type;
}
@ -20,8 +19,12 @@ public class JassLocalStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
localScope.createLocal(this.identifier, this.type);
if (this.type == JassType.INTEGER) {
localScope.createLocal(this.identifier, this.type, IntegerJassValue.ZERO);
}
else {
localScope.createLocal(this.identifier, this.type);
}
return null;
}

View File

@ -8,18 +8,15 @@ import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
public class JassLoopStatement implements JassStatement {
private final int lineNo;
private final List<JassStatement> statements;
public JassLoopStatement(final int lineNo, final List<JassStatement> statements) {
this.lineNo = lineNo;
public JassLoopStatement(final List<JassStatement> statements) {
this.statements = statements;
}
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
while (true) {
for (final JassStatement statement : this.statements) {
final JassValue returnValue = statement.execute(globalScope, localScope, triggerScope);

View File

@ -8,16 +8,10 @@ import com.etheller.interpreter.ast.value.StringJassValue;
public class JassReturnNothingStatement implements JassStatement {
public static final StringJassValue RETURN_NOTHING_NOTICE = new StringJassValue("nothing");
private final int lineNo;
public JassReturnNothingStatement(final int lineNo) {
this.lineNo = lineNo;
}
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
return RETURN_NOTHING_NOTICE;
}

View File

@ -7,18 +7,15 @@ import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
public class JassReturnStatement implements JassStatement {
private final int lineNo;
private final JassExpression expression;
public JassReturnStatement(final int lineNo, final JassExpression expression) {
this.lineNo = lineNo;
public JassReturnStatement(final JassExpression expression) {
this.expression = expression;
}
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
return this.expression.evaluate(globalScope, localScope, triggerScope);
}

View File

@ -8,12 +8,10 @@ import com.etheller.interpreter.ast.scope.TriggerExecutionScope;
import com.etheller.interpreter.ast.value.JassValue;
public class JassSetStatement implements JassStatement {
private final int lineNo;
private final String identifier;
private final JassExpression expression;
public JassSetStatement(final int lineNo, final String identifier, final JassExpression expression) {
this.lineNo = lineNo;
public JassSetStatement(final String identifier, final JassExpression expression) {
this.identifier = identifier;
this.expression = expression;
}
@ -21,7 +19,6 @@ public class JassSetStatement implements JassStatement {
@Override
public JassValue execute(final GlobalScope globalScope, final LocalScope localScope,
final TriggerExecutionScope triggerScope) {
globalScope.setLineNumber(this.lineNo);
final Assignable local = localScope.getAssignableLocal(this.identifier);
if (local != null) {
local.setValue(this.expression.evaluate(globalScope, localScope, triggerScope));

View File

@ -0,0 +1,5 @@
package com.etheller.interpreter.ast.util;
public interface CHandle {
int getHandleId();
}

View File

@ -0,0 +1,5 @@
package com.etheller.interpreter.ast.util;
public class JassSettings {
public static boolean DEBUG = true;
}

View File

@ -1,5 +1,7 @@
package com.etheller.interpreter.ast.value;
import java.util.Arrays;
import com.etheller.interpreter.ast.value.visitor.JassTypeGettingValueVisitor;
public class ArrayJassValue implements JassValue {
@ -8,6 +10,21 @@ public class ArrayJassValue implements JassValue {
public ArrayJassValue(final ArrayJassType type) {
this.type = type;
final JassType primitiveType = this.type.getPrimitiveType();
// Some default values for primitives... in general seems like the user script
// should already do this, so maybe we could take it out for performance later,
// but at the moment it's only a cost when we create a new array (local array)
// which is rare. Anyway, preallocating arrays to size 8192 is very stupid.
if (primitiveType == JassType.INTEGER) {
Arrays.fill(this.data, IntegerJassValue.ZERO);
}
else if (primitiveType == JassType.REAL) {
Arrays.fill(this.data, RealJassValue.ZERO);
}
else if (primitiveType == JassType.BOOLEAN) {
Arrays.fill(this.data, BooleanJassValue.FALSE);
}
}
@Override

View File

@ -22,4 +22,9 @@ public class HandleJassValue implements JassValue {
return visitor.accept(this);
}
@Override
public String toString() {
return this.type.getName() + ":" + this.javaValue;
}
}

View File

@ -1,6 +1,7 @@
package com.etheller.interpreter.ast.value;
public class IntegerJassValue implements JassValue {
public static final JassValue ZERO = new IntegerJassValue(0);
private final int value;
public IntegerJassValue(final int value) {

View File

@ -1,6 +1,7 @@
package com.etheller.interpreter.ast.value;
public class RealJassValue implements JassValue {
public static final JassValue ZERO = new RealJassValue(0);
private final double value;
public RealJassValue(final double value) {

View File

@ -1,6 +1,7 @@
package com.etheller.interpreter.ast.value;
public class StringJassValue implements JassValue {
public static final JassValue EMPTY_STRING = StringJassValue.of("");
private final String value;
public static StringJassValue of(final String value) {

View File

@ -18,6 +18,7 @@ import com.etheller.interpreter.JassParser.EqualsExpressionContext;
import com.etheller.interpreter.JassParser.FalseExpressionContext;
import com.etheller.interpreter.JassParser.FunctionCallExpressionContext;
import com.etheller.interpreter.JassParser.FunctionReferenceExpressionContext;
import com.etheller.interpreter.JassParser.HexIntegerLiteralExpressionContext;
import com.etheller.interpreter.JassParser.IntegerLiteralExpressionContext;
import com.etheller.interpreter.JassParser.MultiplicationExpressionContext;
import com.etheller.interpreter.JassParser.NegateExpressionContext;
@ -77,6 +78,12 @@ public class JassExpressionVisitor extends JassBaseVisitor<JassExpression> {
return new LiteralJassExpression(new IntegerJassValue(Integer.parseInt(ctx.INTEGER().getText())));
}
@Override
public JassExpression visitHexIntegerLiteralExpression(final HexIntegerLiteralExpressionContext ctx) {
return new LiteralJassExpression(
new IntegerJassValue(Integer.parseInt(ctx.HEX_CONSTANT().getText().substring(2), 16)));
}
@Override
public JassExpression visitRawcodeLiteralExpression(final RawcodeLiteralExpressionContext ctx) {
final String stringLiteralText = ctx.RAWCODE().getText();

View File

@ -1,7 +1,6 @@
package com.etheller.interpreter.ast.visitors;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.etheller.interpreter.JassBaseVisitor;
@ -11,7 +10,6 @@ import com.etheller.interpreter.JassParser.GlobalContext;
import com.etheller.interpreter.JassParser.ProgramContext;
import com.etheller.interpreter.JassParser.StatementContext;
import com.etheller.interpreter.JassParser.TypeDefinitionContext;
import com.etheller.interpreter.ast.function.JassFunction;
import com.etheller.interpreter.ast.function.JassNativeManager;
import com.etheller.interpreter.ast.function.UserJassFunction;
import com.etheller.interpreter.ast.scope.GlobalScope;
@ -36,6 +34,7 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
private final JassParametersVisitor jassParametersVisitor = new JassParametersVisitor(this.jassTypeVisitor);
private final JassStatementVisitor jassStatementVisitor = new JassStatementVisitor(this.argumentExpressionHandler,
this.jassTypeVisitor);
private String jassFileName;
@Override
public Void visitBlock(final BlockContext ctx) {
@ -47,7 +46,7 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
else if (ctx.nativeBlock() != null) {
final String text = ctx.nativeBlock().ID().getText();
System.out.println("Registering native: " + text);
this.jassNativeManager.registerNativeCode(text,
this.jassNativeManager.registerNativeCode(ctx.getStart().getLine(), this.jassFileName, text,
this.jassParametersVisitor.visit(ctx.nativeBlock().paramList()),
this.jassTypeVisitor.visit(ctx.nativeBlock().type()), this.globals);
}
@ -62,7 +61,7 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
}
final UserJassFunction userJassFunction = new UserJassFunction(statements,
this.jassParametersVisitor.visit(ctx.paramList()), this.jassTypeVisitor.visit(ctx.type()));
this.globals.defineFunction(ctx.ID().getText(), userJassFunction);
this.globals.defineFunction(ctx.getStart().getLine(), this.jassFileName, ctx.ID().getText(), userJassFunction);
return null;
}
@ -83,16 +82,9 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
final UserJassFunction userJassFunction = new UserJassFunction(statements,
this.jassParametersVisitor.visit(functionBlockContext.paramList()),
this.jassTypeVisitor.visit(functionBlockContext.type()));
this.globals.defineFunction(functionBlockContext.ID().getText(), userJassFunction);
}
final JassFunction mainFunction = this.globals.getFunctionByName("main");
if (mainFunction != null) {
try {
mainFunction.call(Collections.EMPTY_LIST, this.globals, EMPTY_TRIGGER_SCOPE);
}
catch (final Exception exc) {
throw new RuntimeException("Exception on Line " + GlobalScope.getLineNumber(), exc);
}
this.globals.defineFunction(ctx.getStart().getLine(), this.jassFileName,
functionBlockContext.ID().getText(), userJassFunction);
System.out.println("Defining jass user function: " + functionBlockContext.ID().getText());
}
return null;
}
@ -104,4 +96,9 @@ public class JassProgramVisitor extends JassBaseVisitor<Void> {
public JassNativeManager getJassNativeManager() {
return this.jassNativeManager;
}
public void setCurrentFileName(final String jassFile) {
this.jassFileName = jassFile;
this.jassStatementVisitor.setCurrentFileName(jassFile);
}
}

View File

@ -17,6 +17,7 @@ import com.etheller.interpreter.JassParser.ReturnStatementContext;
import com.etheller.interpreter.JassParser.SetStatementContext;
import com.etheller.interpreter.JassParser.SimpleIfStatementContext;
import com.etheller.interpreter.JassParser.StatementContext;
import com.etheller.interpreter.ast.debug.DebuggingJassStatement;
import com.etheller.interpreter.ast.statement.JassArrayedAssignmentStatement;
import com.etheller.interpreter.ast.statement.JassCallStatement;
import com.etheller.interpreter.ast.statement.JassExitWhenStatement;
@ -30,10 +31,12 @@ import com.etheller.interpreter.ast.statement.JassReturnNothingStatement;
import com.etheller.interpreter.ast.statement.JassReturnStatement;
import com.etheller.interpreter.ast.statement.JassSetStatement;
import com.etheller.interpreter.ast.statement.JassStatement;
import com.etheller.interpreter.ast.util.JassSettings;
public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
private final ArgumentExpressionHandler argumentExpressionHandler;
private final JassTypeVisitor jassTypeVisitor;
private String jassFileName;
public JassStatementVisitor(final ArgumentExpressionHandler argumentExpressionHandler,
final JassTypeVisitor jassTypeVisitor) {
@ -44,8 +47,8 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
@Override
public JassStatement visitCallStatement(final CallStatementContext ctx) {
try {
return new JassCallStatement(ctx.getStart().getLine(), ctx.functionExpression().ID().getText(),
this.argumentExpressionHandler.argumentsVisitor.visit(ctx.functionExpression().argsList()));
return wrap(ctx.getStart().getLine(), new JassCallStatement(ctx.functionExpression().ID().getText(),
this.argumentExpressionHandler.argumentsVisitor.visit(ctx.functionExpression().argsList())));
}
catch (final Exception exc) {
throw new RuntimeException(ctx.getText(), exc);
@ -54,25 +57,25 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
@Override
public JassStatement visitSetStatement(final SetStatementContext ctx) {
return new JassSetStatement(ctx.getStart().getLine(), ctx.ID().getText(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()));
return wrap(ctx.getStart().getLine(), new JassSetStatement(ctx.ID().getText(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression())));
}
@Override
public JassStatement visitReturnStatement(final ReturnStatementContext ctx) {
return new JassReturnStatement(ctx.getStart().getLine(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()));
return wrap(ctx.getStart().getLine(),
new JassReturnStatement(this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression())));
}
@Override
public JassStatement visitReturnNothingStatement(final ReturnNothingStatementContext ctx) {
return new JassReturnNothingStatement(ctx.getStart().getLine());
return wrap(ctx.getStart().getLine(), new JassReturnNothingStatement());
}
@Override
public JassStatement visitExitWhenStatement(final ExitWhenStatementContext ctx) {
return new JassExitWhenStatement(ctx.getStart().getLine(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()));
return wrap(ctx.getStart().getLine(),
new JassExitWhenStatement(this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression())));
}
@Override
@ -82,8 +85,8 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
thenStatements.add(visit(statementCtx));
}
final JassStatement elseIfTail = visit(ctx.ifStatementPartial());
return new JassIfElseIfStatement(ctx.getStart().getLine(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()), thenStatements, elseIfTail);
return wrap(ctx.getStart().getLine(), new JassIfElseIfStatement(
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()), thenStatements, elseIfTail));
}
@Override
@ -96,9 +99,9 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
for (final StatementContext statementCtx : ctx.statements(1).statement()) {
elseStatements.add(visit(statementCtx));
}
return new JassIfElseStatement(ctx.getStart().getLine(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()), thenStatements,
elseStatements);
return wrap(ctx.getStart().getLine(),
new JassIfElseStatement(this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()),
thenStatements, elseStatements));
}
@Override
@ -107,7 +110,7 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
for (final StatementContext statementCtx : ctx.statements().statement()) {
statements.add(visit(statementCtx));
}
return new JassLoopStatement(ctx.getStart().getLine(), statements);
return wrap(ctx.getStart().getLine(), new JassLoopStatement(statements));
}
@Override
@ -116,27 +119,41 @@ public class JassStatementVisitor extends JassBaseVisitor<JassStatement> {
for (final StatementContext statementCtx : ctx.statements().statement()) {
thenStatements.add(visit(statementCtx));
}
return new JassIfStatement(ctx.getStart().getLine(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()), thenStatements);
return wrap(ctx.getStart().getLine(), new JassIfStatement(
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression()), thenStatements));
}
@Override
public JassStatement visitArrayedAssignmentStatement(final ArrayedAssignmentStatementContext ctx) {
return new JassArrayedAssignmentStatement(ctx.getStart().getLine(), ctx.ID().getText(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression(0)),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression(1)));
return wrap(ctx.getStart().getLine(),
new JassArrayedAssignmentStatement(ctx.ID().getText(),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression(0)),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.expression(1))));
}
@Override
public JassStatement visitBasicLocal(final BasicLocalContext ctx) {
return new JassLocalStatement(ctx.getStart().getLine(), ctx.ID().getText(),
this.jassTypeVisitor.visit(ctx.type()));
return wrap(ctx.getStart().getLine(),
new JassLocalStatement(ctx.ID().getText(), this.jassTypeVisitor.visit(ctx.type())));
}
@Override
public JassStatement visitDefinitionLocal(final DefinitionLocalContext ctx) {
return new JassLocalDefinitionStatement(ctx.getStart().getLine(), ctx.ID().getText(),
this.jassTypeVisitor.visit(ctx.type()),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.assignTail().expression()));
return wrap(ctx.getStart().getLine(),
new JassLocalDefinitionStatement(ctx.ID().getText(), this.jassTypeVisitor.visit(ctx.type()),
this.argumentExpressionHandler.expressionVisitor.visit(ctx.assignTail().expression())));
}
public void setCurrentFileName(final String jassFile) {
this.jassFileName = jassFile;
}
private static JassStatement wrap(final int lineNo, final JassStatement statement) {
if (JassSettings.DEBUG) {
return new DebuggingJassStatement(lineNo, statement);
}
else {
return statement;
}
}
}