diff --git a/core/assets/badlogic.jpg b/core/assets/badlogic.jpg deleted file mode 100644 index 4390da6..0000000 Binary files a/core/assets/badlogic.jpg and /dev/null differ diff --git a/core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java b/core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java index 94ee309..0143004 100644 --- a/core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java +++ b/core/src/com/etheller/warsmash/WarsmashGdxMapScreen.java @@ -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) { diff --git a/core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java b/core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java index d6dbff8..d411785 100644 --- a/core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java +++ b/core/src/com/etheller/warsmash/WarsmashGdxMenuScreen.java @@ -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(); diff --git a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java index 4a74d06..2a5f678 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/Jass2.java +++ b/core/src/com/etheller/warsmash/parsers/jass/Jass2.java @@ -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.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 group = arguments.get(0).visit(ObjectJassValueVisitor.>getInstance()); final JassFunction callback = arguments.get(1).visit(JassFunctionJassValueVisitor.getInstance()); - for (final CUnit unit : group) { - callback.call(Collections.emptyList(), globalScope, - CommonTriggerExecutionScope.enumScope(triggerScope, unit)); + try { + for (final CUnit unit : group) { + callback.call(Collections.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 force = arguments.get(0) .visit(ObjectJassValueVisitor.>getInstance()); final JassFunction callback = arguments.get(1).visit(JassFunctionJassValueVisitor.getInstance()); - for (final CPlayerJass player : force) { - callback.call(Collections.emptyList(), globalScope, - CommonTriggerExecutionScope.enumScope(triggerScope, player)); + try { + for (final CPlayerJass player : force) { + callback.call(Collections.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.getInstance()); final CRegion region = arguments.get(1).visit(ObjectJassValueVisitor.getInstance()); - final TriggerBooleanExpression boolexpr = arguments.get(2) - .visit(ObjectJassValueVisitor.getInstance()); + final TriggerBooleanExpression boolexpr = nullable(arguments, 2, + ObjectJassValueVisitor.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 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 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 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 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 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 arguments, final GlobalScope globalScope, @@ -3577,6 +3652,9 @@ public class Jass2 { public JassValue call(final List 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 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 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 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 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 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 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 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 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 arguments, final GlobalScope globalScope, final TriggerExecutionScope triggerScope) { - final String funcName = arguments.get(0).visit(ObjectJassValueVisitor.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 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 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 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; + } + } } diff --git a/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprCondition.java b/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprCondition.java index 34ef292..524aebd 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprCondition.java +++ b/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprCondition.java @@ -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(); } diff --git a/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprFilter.java b/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprFilter.java index b3a6e27..c2442d3 100644 --- a/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprFilter.java +++ b/core/src/com/etheller/warsmash/parsers/jass/triggers/BoolExprFilter.java @@ -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(); } diff --git a/core/src/com/etheller/warsmash/parsers/w3x/w3i/RandomUnitTable.java b/core/src/com/etheller/warsmash/parsers/w3x/w3i/RandomUnitTable.java index 3295681..9cbc550 100644 --- a/core/src/com/etheller/warsmash/parsers/w3x/w3i/RandomUnitTable.java +++ b/core/src/com/etheller/warsmash/parsers/w3x/w3i/RandomUnitTable.java @@ -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 units; + private final List units = new ArrayList<>(); public void load(final LittleEndianDataInputStream stream) throws IOException { this.id = stream.readInt(); // TODO is this a War3ID? diff --git a/core/src/com/etheller/warsmash/util/WarsmashConstants.java b/core/src/com/etheller/warsmash/util/WarsmashConstants.java index 61f078b..766bd1d 100644 --- a/core/src/com/etheller/warsmash/util/WarsmashConstants.java +++ b/core/src/com/etheller/warsmash/util/WarsmashConstants.java @@ -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; } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java index 75cbcef..dacdabc 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/War3MapViewer.java @@ -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); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderDestructable.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderDestructable.java index ea02abf..8b442fa 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderDestructable.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/rendersim/RenderDestructable.java @@ -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 } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java index 03df186..f27e09f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CSimulation.java @@ -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); + } + } + } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java index 8051026..2101181 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/CWidget.java @@ -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; } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityView.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityView.java index 05cd811..c64765d 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityView.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/CAbilityView.java @@ -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, diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/GetAbilityByRawcodeVisitor.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/GetAbilityByRawcodeVisitor.java new file mode 100644 index 0000000..554670f --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/abilities/GetAbilityByRawcodeVisitor.java @@ -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 { + 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; + } + +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/ai/AIDifficulty.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/ai/AIDifficulty.java index 681f710..779d694 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/ai/AIDifficulty.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/ai/AIDifficulty.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java index cd540b8..1504732 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/combat/CAttackType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/item/CItemTypeJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/item/CItemTypeJass.java index bde3174..7cfb8ba 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/item/CItemTypeJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/item/CItemTypeJass.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CAllianceType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CAllianceType.java index ea1f28a..61285a5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CAllianceType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CAllianceType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapControl.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapControl.java index 423e458..2e231a1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapControl.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapControl.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapFlag.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapFlag.java index f001bc8..164e3ed 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapFlag.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapFlag.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapPlacement.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapPlacement.java index 29eb00e..e96b458 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapPlacement.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CMapPlacement.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java index dca7627..5bc9b3e 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayer.java @@ -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; + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerColor.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerColor.java index 20cfcf6..0d99690 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerColor.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerColor.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerGameResult.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerGameResult.java index e713d5c..be55ce9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerGameResult.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerGameResult.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerScore.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerScore.java index f0950d8..1b89b71 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerScore.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerScore.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerState.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerState.java index 5da049f..6b3f199 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerState.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CPlayerState.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRace.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRace.java index a3f7f04..5a3642b 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRace.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRace.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRacePreference.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRacePreference.java index 24ff6ac..bc0a07a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRacePreference.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CRacePreference.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CStartLocPrio.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CStartLocPrio.java index 99d7008..82d71f5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CStartLocPrio.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/players/CStartLocPrio.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/region/CRegionTriggerLeave.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/region/CRegionTriggerLeave.java index abf06dc..3927cab 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/region/CRegionTriggerLeave.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/region/CRegionTriggerLeave.java @@ -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); diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CGameState.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CGameState.java index 0cad618..5aed112 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CGameState.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CGameState.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CUnitState.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CUnitState.java index 2272ad4..1dd11e9 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CUnitState.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/state/CUnitState.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/timers/CTimerJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/timers/CTimerJass.java index 8659923..2c4f988 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/timers/CTimerJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/timers/CTimerJass.java @@ -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)) { diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/JassGameEventsWar3.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/JassGameEventsWar3.java index 0383201..6398646 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/JassGameEventsWar3.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/JassGameEventsWar3.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CBlendMode.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CBlendMode.java index 8ea22de..978773f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CBlendMode.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CBlendMode.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CCameraField.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CCameraField.java index b51f0a4..8cb8ed5 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CCameraField.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CCameraField.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CDamageType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CDamageType.java index 09c96af..a770b69 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CDamageType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CDamageType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CEffectType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CEffectType.java index 1d02a97..8824d81 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CEffectType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CEffectType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CFogState.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CFogState.java index 4e849f1..e89752f 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CFogState.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CFogState.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameSpeed.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameSpeed.java index ee44d83..dc8d3ae 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameSpeed.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameSpeed.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameType.java index 6c068a3..d0b3923 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CGameType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDensity.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDensity.java index 0e27016..2104d94 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDensity.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDensity.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDifficulty.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDifficulty.java index 30b1e87..d81081a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDifficulty.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CMapDifficulty.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPathingTypeJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPathingTypeJass.java index 2e82cbe..bddb87d 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPathingTypeJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPathingTypeJass.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPlayerSlotState.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPlayerSlotState.java index e8c219f..9dd9f10 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPlayerSlotState.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CPlayerSlotState.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CRarityControl.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CRarityControl.java index d67015d..320bf1d 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CRarityControl.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CRarityControl.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundType.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundType.java index 14db526..b229183 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundType.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundType.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundVolumeGroup.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundVolumeGroup.java index 3f22881..115728e 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundVolumeGroup.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CSoundVolumeGroup.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CTexMapFlags.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CTexMapFlags.java index 10dee18..b77c8c0 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CTexMapFlags.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CTexMapFlags.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CVersion.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CVersion.java index 6e8cf22..9976f90 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CVersion.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CVersion.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CWeaponSoundTypeJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CWeaponSoundTypeJass.java index f3a6b8f..1a5b2a1 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CWeaponSoundTypeJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/trigger/enumtypes/CWeaponSoundTypeJass.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/CUnitTypeJass.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/CUnitTypeJass.java index 3092f37..ea0d252 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/CUnitTypeJass.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/unit/CUnitTypeJass.java @@ -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(); + } } diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/CHashtable.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/CHashtable.java new file mode 100644 index 0000000..d82b5ea --- /dev/null +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/simulation/util/CHashtable.java @@ -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> parentKeyToChildTable = new HashMap<>(); + + public void save(final Integer parentKey, final Integer childKey, final Object object) { + Map 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 childTable = this.parentKeyToChildTable.get(parentKey); + if (childTable != null) { + return childTable.get(childKey); + } + return null; + } +} diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java index 164ed2b..3b167a4 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MeleeUI.java @@ -354,6 +354,7 @@ public class MeleeUI implements CUnitStateListener, CommandButtonListener, Comma private boolean currentMusicRandomizeIndex; private final List 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 { 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; diff --git a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MenuUI.java b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MenuUI.java index aac3477..013492a 100644 --- a/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MenuUI.java +++ b/core/src/com/etheller/warsmash/viewer5/handlers/w3x/ui/MenuUI.java @@ -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(); diff --git a/jassparser/antlr-src/Jass.g4 b/jassparser/antlr-src/Jass.g4 index 7251574..512f817 100644 --- a/jassparser/antlr-src/Jass.g4 +++ b/jassparser/antlr-src/Jass.g4 @@ -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' ; diff --git a/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassFunction.java b/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassFunction.java new file mode 100644 index 0000000..5c82e9b --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassFunction.java @@ -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 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; + } + +} diff --git a/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassStatement.java b/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassStatement.java new file mode 100644 index 0000000..c3658d8 --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/debug/DebuggingJassStatement.java @@ -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); + } + +} diff --git a/jassparser/src/com/etheller/interpreter/ast/debug/JassException.java b/jassparser/src/com/etheller/interpreter/ast/debug/JassException.java new file mode 100644 index 0000000..e582c09 --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/debug/JassException.java @@ -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 stackTrace = globalScope.copyJassStack(); + final StringBuilder sb = new StringBuilder(message); + for (final JassStackElement element : stackTrace) { + sb.append("\n"); + sb.append(element); + } + return sb.toString(); + } +} diff --git a/jassparser/src/com/etheller/interpreter/ast/debug/JassStackElement.java b/jassparser/src/com/etheller/interpreter/ast/debug/JassStackElement.java new file mode 100644 index 0000000..e9bdd09 --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/debug/JassStackElement.java @@ -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 + ")"; + } +} diff --git a/jassparser/src/com/etheller/interpreter/ast/expression/ArithmeticSigns.java b/jassparser/src/com/etheller/interpreter/ast/expression/ArithmeticSigns.java index 61b2d43..32381ad 100644 --- a/jassparser/src/com/etheller/interpreter/ast/expression/ArithmeticSigns.java +++ b/jassparser/src/com/etheller/interpreter/ast/expression/ArithmeticSigns.java @@ -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()); } } diff --git a/jassparser/src/com/etheller/interpreter/ast/function/AbstractJassFunction.java b/jassparser/src/com/etheller/interpreter/ast/function/AbstractJassFunction.java index af9107f..2e5ae75 100644 --- a/jassparser/src/com/etheller/interpreter/ast/function/AbstractJassFunction.java +++ b/jassparser/src/com/etheller/interpreter/ast/function/AbstractJassFunction.java @@ -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( diff --git a/jassparser/src/com/etheller/interpreter/ast/function/JassNativeManager.java b/jassparser/src/com/etheller/interpreter/ast/function/JassNativeManager.java index 931c918..d26f3d6 100644 --- a/jassparser/src/com/etheller/interpreter/ast/function/JassNativeManager.java +++ b/jassparser/src/com/etheller/interpreter/ast/function/JassNativeManager.java @@ -21,13 +21,14 @@ public class JassNativeManager { this.nameToNativeCode.put(name, nativeCode); } - public void registerNativeCode(final String name, final List parameters, final JassType returnType, - final GlobalScope globals) { + public void registerNativeCode(final int lineNo, final String sourceFile, final String name, + final List 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); } diff --git a/jassparser/src/com/etheller/interpreter/ast/scope/GlobalScope.java b/jassparser/src/com/etheller/interpreter/ast/scope/GlobalScope.java index 7063203..cc3200b 100644 --- a/jassparser/src/com/etheller/interpreter/ast/scope/GlobalScope.java +++ b/jassparser/src/com/etheller/interpreter/ast/scope/GlobalScope.java @@ -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 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 getJassStack() { + return this.jassStack; } - public static int getLineNumber() { - return lineNumber; + public List copyJassStack() { + final List 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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/scope/trigger/Trigger.java b/jassparser/src/com/etheller/interpreter/ast/scope/trigger/Trigger.java index 81c103a..6a04406 100644 --- a/jassparser/src/com/etheller/interpreter/ast/scope/trigger/Trigger.java +++ b/jassparser/src/com/etheller/interpreter/ast/scope/trigger/Trigger.java @@ -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); + } } } diff --git a/jassparser/src/com/etheller/interpreter/ast/scope/variableevent/CLimitOp.java b/jassparser/src/com/etheller/interpreter/ast/scope/variableevent/CLimitOp.java index ca34cbc..d637031 100644 --- a/jassparser/src/com/etheller/interpreter/ast/scope/variableevent/CLimitOp.java +++ b/jassparser/src/com/etheller/interpreter/ast/scope/variableevent/CLimitOp.java @@ -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(); + } } diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassArrayedAssignmentStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassArrayedAssignmentStatement.java index 5b80156..5f42db8 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassArrayedAssignmentStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassArrayedAssignmentStatement.java @@ -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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassCallStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassCallStatement.java index a5e9635..a19ddd4 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassCallStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassCallStatement.java @@ -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 arguments; - public JassCallStatement(final int lineNo, final String functionName, final List arguments) { - this.lineNo = lineNo; + public JassCallStatement(final String functionName, final List 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); diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassExitWhenStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassExitWhenStatement.java index f6fdd0e..4b86268 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassExitWhenStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassExitWhenStatement.java @@ -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; diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseIfStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseIfStatement.java index 5f1f208..d42eaf4 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseIfStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseIfStatement.java @@ -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 thenStatements; private final JassStatement elseifTail; - public JassIfElseIfStatement(final int lineNo, final JassExpression condition, - final List thenStatements, final JassStatement elseifTail) { - this.lineNo = lineNo; + public JassIfElseIfStatement(final JassExpression condition, final List 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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseStatement.java index 20b9719..cfa67a4 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfElseStatement.java @@ -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 thenStatements; private final List elseStatements; - public JassIfElseStatement(final int lineNo, final JassExpression condition, - final List thenStatements, final List elseStatements) { - this.lineNo = lineNo; + public JassIfElseStatement(final JassExpression condition, final List thenStatements, + final List 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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfStatement.java index 8ef37d0..7293bb1 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassIfStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassIfStatement.java @@ -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 thenStatements; - public JassIfStatement(final int lineNo, final JassExpression condition, final List thenStatements) { - this.lineNo = lineNo; + public JassIfStatement(final JassExpression condition, final List 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 diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalDefinitionStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalDefinitionStatement.java index 2b96f48..daf8298 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalDefinitionStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalDefinitionStatement.java @@ -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; diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalStatement.java index 448aa27..7823bfa 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassLocalStatement.java @@ -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; } diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassLoopStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassLoopStatement.java index a402d86..2f7f81e 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassLoopStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassLoopStatement.java @@ -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 statements; - public JassLoopStatement(final int lineNo, final List statements) { - this.lineNo = lineNo; + public JassLoopStatement(final List 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); diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnNothingStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnNothingStatement.java index ee96f44..16b6d75 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnNothingStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnNothingStatement.java @@ -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; } diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnStatement.java index adb1b4e..3a4e6a7 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassReturnStatement.java @@ -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); } diff --git a/jassparser/src/com/etheller/interpreter/ast/statement/JassSetStatement.java b/jassparser/src/com/etheller/interpreter/ast/statement/JassSetStatement.java index e8249d4..bd914b5 100644 --- a/jassparser/src/com/etheller/interpreter/ast/statement/JassSetStatement.java +++ b/jassparser/src/com/etheller/interpreter/ast/statement/JassSetStatement.java @@ -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)); diff --git a/jassparser/src/com/etheller/interpreter/ast/util/CHandle.java b/jassparser/src/com/etheller/interpreter/ast/util/CHandle.java new file mode 100644 index 0000000..62b3b70 --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/util/CHandle.java @@ -0,0 +1,5 @@ +package com.etheller.interpreter.ast.util; + +public interface CHandle { + int getHandleId(); +} diff --git a/jassparser/src/com/etheller/interpreter/ast/util/JassSettings.java b/jassparser/src/com/etheller/interpreter/ast/util/JassSettings.java new file mode 100644 index 0000000..a000c78 --- /dev/null +++ b/jassparser/src/com/etheller/interpreter/ast/util/JassSettings.java @@ -0,0 +1,5 @@ +package com.etheller.interpreter.ast.util; + +public class JassSettings { + public static boolean DEBUG = true; +} diff --git a/jassparser/src/com/etheller/interpreter/ast/value/ArrayJassValue.java b/jassparser/src/com/etheller/interpreter/ast/value/ArrayJassValue.java index 2a33879..dbff226 100644 --- a/jassparser/src/com/etheller/interpreter/ast/value/ArrayJassValue.java +++ b/jassparser/src/com/etheller/interpreter/ast/value/ArrayJassValue.java @@ -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 diff --git a/jassparser/src/com/etheller/interpreter/ast/value/HandleJassValue.java b/jassparser/src/com/etheller/interpreter/ast/value/HandleJassValue.java index 78032fd..1ffd195 100644 --- a/jassparser/src/com/etheller/interpreter/ast/value/HandleJassValue.java +++ b/jassparser/src/com/etheller/interpreter/ast/value/HandleJassValue.java @@ -22,4 +22,9 @@ public class HandleJassValue implements JassValue { return visitor.accept(this); } + @Override + public String toString() { + return this.type.getName() + ":" + this.javaValue; + } + } diff --git a/jassparser/src/com/etheller/interpreter/ast/value/IntegerJassValue.java b/jassparser/src/com/etheller/interpreter/ast/value/IntegerJassValue.java index e8953c8..8eb4bc8 100644 --- a/jassparser/src/com/etheller/interpreter/ast/value/IntegerJassValue.java +++ b/jassparser/src/com/etheller/interpreter/ast/value/IntegerJassValue.java @@ -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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/value/RealJassValue.java b/jassparser/src/com/etheller/interpreter/ast/value/RealJassValue.java index 5340fbb..0dcde87 100644 --- a/jassparser/src/com/etheller/interpreter/ast/value/RealJassValue.java +++ b/jassparser/src/com/etheller/interpreter/ast/value/RealJassValue.java @@ -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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/value/StringJassValue.java b/jassparser/src/com/etheller/interpreter/ast/value/StringJassValue.java index 9cbcbb8..87b3aae 100644 --- a/jassparser/src/com/etheller/interpreter/ast/value/StringJassValue.java +++ b/jassparser/src/com/etheller/interpreter/ast/value/StringJassValue.java @@ -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) { diff --git a/jassparser/src/com/etheller/interpreter/ast/visitors/JassExpressionVisitor.java b/jassparser/src/com/etheller/interpreter/ast/visitors/JassExpressionVisitor.java index 2c52f30..15900fe 100644 --- a/jassparser/src/com/etheller/interpreter/ast/visitors/JassExpressionVisitor.java +++ b/jassparser/src/com/etheller/interpreter/ast/visitors/JassExpressionVisitor.java @@ -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 { 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(); diff --git a/jassparser/src/com/etheller/interpreter/ast/visitors/JassProgramVisitor.java b/jassparser/src/com/etheller/interpreter/ast/visitors/JassProgramVisitor.java index 59a2a95..e107a38 100644 --- a/jassparser/src/com/etheller/interpreter/ast/visitors/JassProgramVisitor.java +++ b/jassparser/src/com/etheller/interpreter/ast/visitors/JassProgramVisitor.java @@ -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 { 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 { 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 { } 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 { 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 { public JassNativeManager getJassNativeManager() { return this.jassNativeManager; } + + public void setCurrentFileName(final String jassFile) { + this.jassFileName = jassFile; + this.jassStatementVisitor.setCurrentFileName(jassFile); + } } diff --git a/jassparser/src/com/etheller/interpreter/ast/visitors/JassStatementVisitor.java b/jassparser/src/com/etheller/interpreter/ast/visitors/JassStatementVisitor.java index cbffaa0..7d1eb13 100644 --- a/jassparser/src/com/etheller/interpreter/ast/visitors/JassStatementVisitor.java +++ b/jassparser/src/com/etheller/interpreter/ast/visitors/JassStatementVisitor.java @@ -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 { 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 { @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 { @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 { 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 { 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 { 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 { 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; + } } }