Properties break map in Eclipse/JavaFX/FXGL

I loaded a .tmx into a Java Project using Maven, JavaFX/FXGL and it worked ok. But as soon as I added a custom properties (like bool blocking = true) to the tileset or any of the objects, I get an error that Image dimensions must be positive (w,h > 0). I’m not an expert, so it’s been tough to fix (and I’m not even sure if it can be.) I tried everything over the past few days and isolated that this only happens once I click the + button and add custom properties to something such as a tile. Or when I’m naming things to be able to grab them with the code. All the fixes I’ve found point to it being a problem with the files, but it’s not. The map opens fine in my program so long as there are no custom properties. I even downgraded to 1.9 because there was indication that maybe maven wasn’t playing nicely with 1.11. Downgrading didn’t help. I’m just wondering if anyone else had this issue because I can’t find any documentation about it.

Message: Initialization failed
Type: RuntimeException
Method: FXGLApplication$InitAppTask.failed()
Line: FXGLApplication.kt:347

java.lang.RuntimeException: Initialization failed
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.failed(FXGLApplication.kt:347)
at javafx.graphics@21.0.1/javafx.concurrent.Task.setState(Task.java:710)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.lambda$call$2(Task.java:1429)
at javafx.graphics@21.0.1/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at javafx.graphics@21.0.1/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
at javafx.graphics@21.0.1/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at javafx.graphics@21.0.1/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics@21.0.1/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: com.almasb.fxgl.entity.level.LevelLoadingException: Image dimensions must be positive (w,h > 0)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:77)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.services.FXGLAssetLoaderService.loadLevel(FXGLAssetLoaderService.kt:449)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL$Companion.setLevelFromMap(FXGL.kt:643)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.dsl.FXGL.setLevelFromMap(FXGL.kt)
at com.mygame/com.mygame.MyGameApp.initGame(MyGameApp.java:89)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.initGame(FXGLApplication.kt:343)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:321)
at com.almasb.fxgl.all@21.1/com.almasb.fxgl.app.FXGLApplication$InitAppTask.call(FXGLApplication.kt:313)
at javafx.graphics@21.0.1/javafx.concurrent.Task$TaskCallable.call(Task.java:1399)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
… 1 more
Caused by: java.lang.IllegalArgumentException: Image dimensions must be positive (w,h > 0)
at javafx.graphics@21.0.1/javafx.scene.image.Image.(Image.java:743)
at javafx.graphics@21.0.1/javafx.scene.image.WritableImage.(WritableImage.java:77)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:143)
at com.almasb.fxgl.core@21.1/com.almasb.fxgl.texture.ImagesKt.resize(Images.kt:127)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadImage(TilesetLoader.kt:448)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TilesetLoader.loadView(TilesetLoader.kt:156)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:99)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader$createTileLayerEntities$1.invoke(TMXLevelLoader.kt:88)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities$lambda$3(TMXLevelLoader.kt:88)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.createTileLayerEntities(TMXLevelLoader.kt:116)
at com.almasb.fxgl.entity@21.1/com.almasb.fxgl.entity.level.tiled.TMXLevelLoader.load(TMXLevelLoader.kt:58)
… 14 more

I’m guessing your tileset is a “Based on Tileset Image” tileset? Looking at your stack trace and the FXGL code, it looks like it’s trying to load an image from the tile, rather than the tileset. It uses tileset.isSpriteSheet in Tileset.kt to determine whether a Tileset is a spritesheet (“Based on Tileset Image”) or not (“Collection of Images”), but isSpritesheet is effectively checking whether the Tileset has any <tile> elements - this is incorrect, because <tile>s can exist for reasons other than defining the image of a tile, such as holding your custom properties. I imagine adding animations or terrains would also cause this breakage.

This is a bug in FXGL, and you should report it to them. A better check would be whether the Tileset itself has an Image set - if it does, that image should be used, and if it does not, then the Tiles should have images to use.