Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jass parser cannot find config function in map script #64

Open
tdauth opened this issue Dec 12, 2024 · 2 comments
Open

Jass parser cannot find config function in map script #64

tdauth opened this issue Dec 12, 2024 · 2 comments

Comments

@tdauth
Copy link
Contributor

tdauth commented Dec 12, 2024

I get this error in my error log:

Exception in thread "LWJGL Application" com.etheller.interpreter.ast.debug.JassException: Exception on Line -1
	at com.etheller.warsmash.parsers.jass.Jass2$ConfigEnvironment.config(Jass2.java:9390)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.loadAndCacheMapConfigs(MenuUI.java:1770)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.startMap(MenuUI.java:1722)
	at com.etheller.warsmash.WarsmashGdxMenuScreen.startMap(WarsmashGdxMenuScreen.java:925)
	at com.etheller.warsmash.desktop.DesktopLauncher$1.run(DesktopLauncher.java:124)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.executeRunnables(LwjglApplication.java:309)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:236)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:138)
Caused by: java.lang.IllegalStateException: Unable to spawn jass thread for function name: config
	at com.etheller.interpreter.ast.scope.GlobalScope.createThread(GlobalScope.java:570)
	at com.etheller.warsmash.parsers.jass.Jass2$ConfigEnvironment.config(Jass2.java:9384)
	... 7 more

The map script should be this: https://raw.githubusercontent.com/tdauth/wowr/refs/heads/master/wowr.w3x/war3map.j

It has no syntax errors with pjass. The map contains a custom Scripts/common.j and Scripts/common.ai.

There is a config function:

function config takes nothing returns nothing
    call SetMapName("TRIGSTR_001")
    call SetMapDescription("TRIGSTR_003")
    call SetPlayers(23)
    call SetTeams(23)
    call SetGamePlacement(MAP_PLACEMENT_TEAMS_TOGETHER)

    call DefineStartLocation(0, - 16512.0, - 22272.0)
    call DefineStartLocation(1, - 16512.0, - 22272.0)
    call DefineStartLocation(2, - 16512.0, - 22272.0)
    call DefineStartLocation(3, - 16512.0, - 22272.0)
    call DefineStartLocation(4, - 16512.0, - 22272.0)
    call DefineStartLocation(5, - 16512.0, - 22272.0)
    call DefineStartLocation(6, - 16512.0, - 22272.0)
    call DefineStartLocation(7, - 16512.0, - 22272.0)
    call DefineStartLocation(8, - 16512.0, - 22272.0)
    call DefineStartLocation(9, - 16512.0, - 22272.0)
    call DefineStartLocation(10, - 16512.0, - 22272.0)
    call DefineStartLocation(11, - 16512.0, - 22272.0)
    call DefineStartLocation(12, - 16512.0, - 22272.0)
    call DefineStartLocation(13, - 16512.0, - 22272.0)
    call DefineStartLocation(14, - 16512.0, - 22272.0)
    call DefineStartLocation(15, - 16512.0, - 22272.0)
    call DefineStartLocation(16, - 16512.0, - 22272.0)
    call DefineStartLocation(17, - 16512.0, - 22272.0)
    call DefineStartLocation(18, - 16512.0, - 22272.0)
    call DefineStartLocation(19, - 16512.0, - 22272.0)
    call DefineStartLocation(20, - 16512.0, - 22272.0)
    call DefineStartLocation(21, - 16512.0, - 22272.0)
    call DefineStartLocation(22, - 9664.0, - 25088.0)

    // Player setup
    call InitCustomPlayerSlots()
    call InitCustomTeams()
    call InitAllyPriorities()
endfunction

I have no idea why it is not found.

I tried to read my file in JassTest.main and although dataSource.getResourceAsStream("war3map.j") gives me my full code file and I can write it as output, smashJassParser.scanAndParse does not produce anything. The number of errors is 0 and there is no exception.

Now I found the issue in the .jass.log

Caused by: com.etheller.interpreter.ast.debug.JassException: Undefined function: BlzSetUnitRealFieldBJ
	at com.etheller.interpreter.ast.scope.DefaultScope.createException(DefaultScope.java:144)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.insertTypeCastInstructionsOrFail(InstructionAppendingJassStatementVisitor.java:599)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.performParentlessMethodCall(InstructionAppendingJassStatementVisitor.java:582)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.insertFunctionCallInstructions(InstructionAppendingJassStatementVisitor.java:711)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.visit(InstructionAppendingJassStatementVisitor.java:696)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.visit(InstructionAppendingJassStatementVisitor.java:74)
	at com.etheller.interpreter.ast.expression.FunctionCallJassExpression.accept(FunctionCallJassExpression.java:16)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.insertExpressionInstructions(InstructionAppendingJassStatementVisitor.java:423)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.visit(InstructionAppendingJassStatementVisitor.java:148)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.visit(InstructionAppendingJassStatementVisitor.java:74)
	at com.etheller.interpreter.ast.statement.JassCallExpressionStatement.accept(JassCallExpressionStatement.java:14)
	at com.etheller.interpreter.ast.execution.instruction.InstructionAppendingJassStatementVisitor.visit(InstructionAppendingJassStatementVisitor.java:412)
	... 21 more
Caused by: java.lang.IllegalArgumentException
	... 32 more

so I have to change the Blizzard.j

After adding a new folder with scripts/Blizzard.j it still does not use the new file. I placed the folder as first entry but maybe it has to be the last entry.

Type05=Folder
Path05="/home/xxx/privaterepos/Warcraft III/war3"

The problem for me is the lack of documentation in the ini file which entry has a higher priority. Placing it at first entry does not load my Blizzard.j and placing it last doesn't either.
The log files should also be documented in the README, so it is clear for everyone where you can find errors and JASS parsing errors.
It would be helpful to have every file loading + it's data source in the log like:

Loading file "scripts/Blizzard.j" from data source "../Warcraft III/war3/scripts/".
@Retera
Copy link
Owner

Retera commented Dec 13, 2024

Be careful, on a Linux based system the "Folder" data source is often messed up because it is case sensitive. This can easily make it that your Reforged override of the Blizzard.j is not found, such as if the game requests Scripts\Blizzard.j but you provide scripts/Blizzard.j which is a different folder on Linux.

@tdauth
Copy link
Contributor Author

tdauth commented Dec 16, 2024

You are correct. I had to rename it into "Scripts".

Now the map loading screen is shown but then it crashes with:

Exception in thread "LWJGL Application" java.lang.NullPointerException: Cannot invoke "com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRace.getId()" because "race" is null
	at com.etheller.warsmash.viewer5.handlers.w3x.simulation.players.CRaceManager.get(CRaceManager.java:48)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI.main(MeleeUI.java:534)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.toggle.MeleeToggleUI.main(MeleeToggleUI.java:92)
	at com.etheller.warsmash.WarsmashGdxMapScreen.show(WarsmashGdxMapScreen.java:207)
	at com.badlogic.gdx.Game.setScreen(Game.java:63)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.update(MenuUI.java:1917)

It seems to pass null here:

final CRace race = this.localPlayer.getRace();
final CRaceManagerEntry raceEntry = WarsmashConstants.RACE_MANAGER.get(race);

for a Computer player which has an open slot and hence has no race?

From my understanding you set the local player index here:

	public MapLoader createMapLoader(final War3Map war3Map, final War3MapW3i w3iFile, final int localPlayerIndex)
			throws IOException {
		this.localPlayerIndex = localPlayerIndex;
		this.mapMpq = war3Map;
		this.lastLoadedMapInformation = w3iFile;

		return new MapLoader(war3Map, w3iFile, localPlayerIndex);
	}

it is set to 0 which is the red player but red has no default race (selectable). Note it is a Reforged map so maybe the player format is different?

This is the part of my map script generated by the WE:

//***************************************************************************
//*
//*  Players
//*
//***************************************************************************

function InitCustomPlayerSlots takes nothing returns nothing

    // Player 0
    call SetPlayerStartLocation(Player(0), 0)
    call ForcePlayerStartLocation(Player(0), 0)
    call SetPlayerColor(Player(0), ConvertPlayerColor(0))
    call SetPlayerRacePreference(Player(0), RACE_PREF_RANDOM)
    call SetPlayerRaceSelectable(Player(0), true)
    call SetPlayerController(Player(0), MAP_CONTROL_USER)

I made a temporary fix with this line:

if (race == null || entry.getRaceId() == race.getId()) {

but I think it should set a random race or a fixed one from the ini. I know I could specify races in the ini as well.

After fixing this issue I know get this one:

Exception in thread "LWJGL Application" java.lang.IndexOutOfBoundsException: Index: 0
	at java.base/java.util.Collections$EmptyList.get(Collections.java:4586)
	at com.etheller.warsmash.viewer5.handlers.w3x.rendersim.ability.AbilityDataUI.<init>(AbilityDataUI.java:195)
	at com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer.setGameUI(War3MapViewer.java:1787)
	at com.etheller.warsmash.WarsmashGdxMapScreen$1.onCreate(WarsmashGdxMapScreen.java:191)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI.main(MeleeUI.java:540)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.toggle.MeleeToggleUI.main(MeleeToggleUI.java:92)
	at com.etheller.warsmash.WarsmashGdxMapScreen.show(WarsmashGdxMapScreen.java:207)
	at com.badlogic.gdx.Game.setScreen(Game.java:63)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.update(MenuUI.java:1917)
	at com.etheller.warsmash.WarsmashGdxMenuScreen.render(WarsmashGdxMenuScreen.java:568)
	at com.badlogic.gdx.Game.render(Game.java:48)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:259)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:138)

which I had to fix with an if:

final int index = Math.max(0, Math.min(i, targetAttachmentIndexMax));
				if (index < targetArtPaths.size()) {
					final String modelPath = targetArtPaths.get(index);
					final String attachmentPointKey = tryGet(TARGET_ART_ATTACHMENT_POINT, i);
					final List<String> attachmentPoints = abilityTypeData.getFieldAsList(attachmentPointKey);
					targetArt.add(new EffectAttachmentUI(modelPath, attachmentPoints));
				}

Now I get this which makes sense since I have no Reforged CASC archives:

Attempting to load non-existant file: ReplaceableTextures\.blp
java.lang.IllegalArgumentException: input == null!
	at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1358)
	at com.etheller.warsmash.viewer5.handlers.blp.BlpTexture.load(BlpTexture.java:30)
	at com.etheller.warsmash.viewer5.Resource.loadData(Resource.java:28)
	at com.etheller.warsmash.viewer5.ModelViewer.load(ModelViewer.java:197)
	at com.etheller.warsmash.viewer5.handlers.mdx.MdxModel.load(MdxModel.java:202)
	at com.etheller.warsmash.viewer5.handlers.mdx.MdxModel.load(MdxModel.java:331)
	at com.etheller.warsmash.viewer5.Resource.loadData(Resource.java:28)
	at com.etheller.warsmash.viewer5.ModelViewer.load(ModelViewer.java:197)
	at com.etheller.warsmash.viewer5.handlers.w3x.War3MapViewer.loadModelMdx(War3MapViewer.java:2217)
	at com.etheller.warsmash.parsers.fdf.GameUI.setSpriteFrameModel(GameUI.java:1548)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI.main(MeleeUI.java:1344)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.toggle.MeleeToggleUI.main(MeleeToggleUI.java:92)
	at com.etheller.warsmash.WarsmashGdxMapScreen.show(WarsmashGdxMapScreen.java:207)
	at com.badlogic.gdx.Game.setScreen(Game.java:63)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.update(MenuUI.java:1917)
	at com.etheller.warsmash.WarsmashGdxMenuScreen.render(WarsmashGdxMenuScreen.java:568)
	at com.badlogic.gdx.Game.render(Game.java:48)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:259)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:138)
Exception in thread "LWJGL Application" java.lang.IllegalStateException: Missing texture: ReplaceableTextures\TeamColor\TeamColor16.blp
	at com.etheller.warsmash.util.ImageUtils.getAnyExtensionImageFixRGB(ImageUtils.java:67)
	at com.etheller.warsmash.util.ImageUtils.getAnyExtensionTexture(ImageUtils.java:36)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI.createMinimap(MeleeUI.java:508)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MeleeUI.main(MeleeUI.java:1353)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.toggle.MeleeToggleUI.main(MeleeToggleUI.java:92)
	at com.etheller.warsmash.WarsmashGdxMapScreen.show(WarsmashGdxMapScreen.java:207)
	at com.badlogic.gdx.Game.setScreen(Game.java:63)
	at com.etheller.warsmash.viewer5.handlers.w3x.ui.MenuUI.update(MenuUI.java:1917)
	at com.etheller.warsmash.WarsmashGdxMenuScreen.render(WarsmashGdxMenuScreen.java:568)
	at com.badlogic.gdx.Game.render(Game.java:48)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:259)
	at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:138)

However, it could still work even without loading certain textures. Just show them green like Warcraft III does.

You could add some check here when loading minimap textures to avoid this:

		final Texture[] teamColors = new Texture[WarsmashConstants.MAX_PLAYERS];
		for (int i = 0; i < teamColors.length; i++) {
			teamColors[i] = ImageUtils.getAnyExtensionTexture(war3MapViewer.dataSource,
					"ReplaceableTextures\\" + ReplaceableIds.getPathString(1) + ReplaceableIds.getIdString(i) + ".blp");
		}

Maybe check in

 ImageUtils.getAnyExtensionTexture

if the file can be found and return something empty instead or if it can handle null just return null after checking.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants