Skip to content

Latest commit

 

History

History
240 lines (186 loc) · 15.2 KB

Troubleshooting.md

File metadata and controls

240 lines (186 loc) · 15.2 KB

Troubleshooting

This is organized as a list of possible messages or signs there is a problem, followed by any ways that help resolve those problems.

This guide is brand new, and will be added to as new solutions are found for problems.

Some older docs mention Gradle tasks using a "desktop" module.

This would include docs telling you to run a Gradle task like desktop:run or desktop:dist. The solution is almost always to just change desktop to lwjgl3, since there is an lwjgl3 module in most Liftoff projects where gdx-setup would call it desktop. The reason for this is that Liftoff can generate modules using either lwjgl2, which is what gdx-setup used to call desktop, and lwjgl3, which is what it now calls desktop. Liftoff can even generate them both in one parent project, which can be handy for using gdx-tools in the lwjgl2 project.

Of the two, you almost always should be using LWJGL3 in new code; LWJGL2 hasn't been updated in 9 years, and won't see future updates. LWJGL3 also supports more target hardware, from ARM Linux machines like a Raspberry Pi, to M1 and newer Macs using Apple Silicon processors. You might need LWJGL2 to port older projects in specific cases; doing that prevents customers who have the latest Mac hardware from running your game natively. Those customers might still be able to use virtualization software to run Windows games on their Mac, though. LWJGL3 should work out of the box on Mac, thanks in part to the StartupHelper class distributed in new LWJGL3 projects that Liftoff creates.

When importing an Android project, an error mentions SeekableByteChannel.

Specifically, the error involves void org.apache.commons.compress.archivers.zip.ZipFile.<init>(java.nio.channels.SeekableByteChannel)'. The solution for this is to install the Android Build Tools, version 33.0.2 . I don't know if newer versions work as well, but you can have 33.0.2 installed in addition to other versions.

To install new build tools, go to Tools -> Android -> SDK Manager, SDK Tools tab, check "Show Package Details" at the bottom, select Build Tools version 33.0.2, and click Apply or OK. Then follow the installation steps.

When importing an iOS project, an error mentions SeekableByteChannel.

Like the above error, this involves void org.apache.commons.compress.archivers.zip.ZipFile.<init>(java.nio.channels.SeekableByteChannel)'. This has to do with the placement of the robovm plugin, which as of RoboVM 2.3.20 needs to be in ios/build.gradle, not the root build.gradle. This is automatically fixed in projects generated by gdx-liftoff 1.12.0.1 and later, but if you're for any reason using an older version, you can replace the top of ios/build.gradle with:

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath "com.mobidevelop.robovm:robovm-gradle-plugin:$robovmVersion"
  }
}
apply plugin: 'robovm'

[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

(Starting with the line that sets encoding, everything else is the same.) You will also need to remove any mention of robovm plugin from the top of the root build.gradle file; this means a line that starts with classpath and a line apply plugin: 'robovm'.

A project that contains an Android module fails to run, saying Android Gradle plugin requires Java 17 to run.

Well, install Java 17 or higher and try again. You may need to set your JDK in your IDE. In IntelliJ IDEA, it's under File -> Project Structure; in that window, you can even download a JDK automatically in the SDKs tab by clicking + and then Download JDK. Android Studio doesn't provide as many ways to configure the JDK because it should include one that works with the latest Android tools already.

A Kotlin project that contains an Android module gives the message jvm target compatibility should be set to the same Java version.

This should be fixed in 1.12.0.1 by using toolchains, or in 1.12.1.7 using Kotlin's jvmTarget option; if that doesn't work for you, here are other options.

The simplest solution here is to set your JDK to a Java 17 one and to change java.sourceCompatibility and java.targetCompatibility to 11 each. You may need to set this for both Java and Kotlin, and they must use the same versions across the board. You can also set the release option to the same version as targetCompatibility to help with some incompatibilities between versions; this is only available if you are using Java 9 or later.

java.sourceCompatibility = 11
java.targetCompatibility = 11
if (JavaVersion.current().isJava9Compatible()) {
        compileJava.options.release.set(11)
}
kotlin.compilerOptions.jvmTarget.set(JvmTarget.JVM_11)

Another solution is to use toolchains. In your root build.gradle, you can try adding

kotlin {
  jvmToolchain(17)
}

(Probably adding it at the bottom of the file makes the most sense.) You still need to change sourceCompatibility and targetCompatibility to the same version as your toolchain; these affect Java, while the toolchain should help Kotlin.

Running a Kotlin launcher via IDEA's or Android Studio's "green triangle" button in the margin fails.

This can be identified by an error message appearing such as:

Error: Could not find or load main class some.liftoff.project.lwjgl3.Lwjgl3Launcher
Caused by: java.lang.ClassNotFoundException: some.liftoff.project.lwjgl3.Lwjgl3Launcher

The simplest solution I've found for this is to try it again in exactly the same way. You actually can expect a different result! The first failure seems to set something necessary up in the IDE, and so later attempts work. If this still fails on later tries, you can try reimporting/refreshing/syncing the Gradle project (I don't know what each IDE calls it, but the button may look like two circling arrows in the Gradle sidebar, may be in a bar that pops up at the top, or may be a tiny button with just those circling arrows). Then try it again (twice, if needed) and see if it works.

Why does this work at all? 🤷‍♂️

Some steps were taken to try to address this in gdx-liftoff 1.12.1.5, but they can't seem to fully eliminate this problem on the very first run. They may be what fixes it for the second and later runs, though.

Toolchains aren't working or are slow.

This is to be expected in 1.12.1.4, because some configuration was missing for Kotlin projects. That absence has been fixed in 1.12.1.5. In that version and in 1.12.1.6, Java also uses toolchains, the same way Kotlin does. This means there can be a long download for the first time you launch a gdx-liftoff project, but the download will get a JDK and keep it for any future projects to use (as long as they need the same version). This can be useful if someone wants to build your project but doesn't necessarily start with the right JVM version -- toolchains ensure they get the right one.

A good option for cross-platform building is to keep the language level on 11 (supported by everything except RoboVM). This works even on Android; even with its requirements for Java 17 in other places, using a toolchain JDK 11 seems to keep away from those requirements. A JDK 17 may still be needed for other parts of an Android build.

Version 1.12.1.7 does not use toolchains because some simpler ways to accomplish the same things became feasible.

Graal Native Image isn't working (in any of various ways).

First, ensure that you changed enableGraalNative=false to enableGraalNative=true in gradle.properties. This enables the rest of the Graal code, including downloading dependencies once you re-sync the project.

On Windows, you also have to make sure a (rather recent) Visual Studio is installed and has C++ tools installed. The C++ tools aren't checked by default when first installing Visual Studio. There may be issues with some non-US locales when the Native Image tools try to locate Visual Studio programs/scripts. If you encounter these and have a non-English-language and/or non-US locale, you may want to try this StackOverflow answer's solution. You can also launch the Visual Studio x64 Native Tools command prompt (it's in the start menu by default), navigate to your Liftoff project, and launch gradlew lwjgl3:nativeCompile from there, which may work better.

The asset-location code was subtly broken in Liftoff 1.12.1.3 in some cases, namely when assets were in subfolders. This should be fixed in 1.12.1.4; if you are updating a 1.12.1.3 project that uses Graal Native Image, I recommend copying in the whole nativeimage.gradle file to replace the existing one (unless you have edited it) from either a new 1.12.1.4 or higher project or the same file from the generated demo.

There are probably a lot of ways Graal projects can have issues that I don't know about yet. There aren't many users for Graal Native Image in the Java gamedev space right now, but it's a good option for releasing small executables that are relatively hard to decompile (though not impossible). If more people start using Graal Native Image, this section will likely grow.

You receive compile-time errors in a GWT project made with Liftoff 1.12.1.6 or newer.

Liftoff 1.12.1.6 is the first to use GWT 2.11.0, which is almost entirely backwards-compatible... at an API level, at least. It has different dependencies for gwt-user, both because the version is newer, and that JAR is provided in a different "group" -- org.gwtproject:gwt-user:2.11.0 instead of the older com.google.gwt:gwt-user:2.8.2.

Before I start with the general solution, there's often a much easier one: for libraries that Liftoff has in its third-party extensions, any that need special treatment for GWT should already have that taken care of. The rest of this is only needed if a library you want to use isn't known to Liftoff and depends on an older GWT version.

Any library dependencies, not installed via a checkbox in Liftoff, that have code specifically for GWT, and depend either directly on gwt-user (or gwt-dev) or indirectly via any version of com.badlogicgames.gdx:gdx-backend-gwt, can trigger version conflicts from two different releases of GWT. That means if you are trying to use 2.11.0, but 2.10.0, 2.8.2, or 2.8.0 gets into the dependencies, because the groups are different, the older version won't be replaced by the newer one. The solution is to exclude gwt-user (or the gdx-backend-gwt in the com.badlogicsgames.gdx group) from any dependencies that themselves depend on the older GWT. You can identify which dependencies these are by running the Gradle task gradlew html:dependencies, and searching through it for com.google.gwt:gwt-user . The output you're trying to find looks like this:

+--- com.crashinvaders.basisu:basisu-gdx-gwt:1.0.0
|    +--- com.crashinvaders.basisu:basisu-gdx:1.0.0 (*)
|    \--- com.badlogicgames.gdx:gdx-backend-gwt:1.12.0
|         +--- com.badlogicgames.gdx:gdx:1.12.0 -> 1.12.1 (*)
|         \--- com.google.gwt:gwt-user:2.8.2
|              +--- com.google.jsinterop:jsinterop-annotations:1.0.2 -> 2.0.2
|              +--- javax.validation:validation-api:1.0.0.GA
|              +--- javax.servlet:javax.servlet-api:3.1.0
|              \--- org.w3c.css:sac:1.3

Right in the middle there is gwt-user 2.8.2 . Once you've found all the places that depend on old gwt-user, you'll need to add an "exclude" to each dependency that was trying to obtain the old gwt-user. The new one should be kept; it's in org.gwtproject:gwt-user. The change to add an exclude block isn't too hard, but there's a lot of Gradle syntax involved. You find an existing dependency, such as:

implementation "com.crashinvaders.basisu:basisu-gdx-gwt:$gdxBasisUniversalVersion:sources"

Then make sure the quoted String is also in parentheses (I don't know why this is needed), and after that add a curly brace block to configure that line.

implementation("com.crashinvaders.basisu:basisu-gdx-gwt:$gdxBasisUniversalVersion:sources") {
  exclude group: "com.badlogicgames.gdx", module: "gdx-backend-gwt"
}

It is approximately equivalent to exclude the older gwt-user directly, and this may be better for some libraries that don't depend on libGDX, but do depend on GWT. You could do that with this block instead of the one above:

implementation("com.crashinvaders.basisu:basisu-gdx-gwt:$gdxBasisUniversalVersion:sources") {
  exclude group: "com.google.gwt", module: "gwt-user"
}

If a dependency has two parts that both depend on GWT, typically one with a :sources classifier at the end and one without :sources, then both need to be given the same exclude block in curly braces.

Once every dependency on older GWT has been excluded, you should be able to run html:superDev or html:dist without any issues. From this, anyway.

Libraries known to be affected by this include Artemis-ODB, the official Box2D, gdx-facebook, the official gdx-controllers, the unofficial gdx-controllerutils, Guacamole, and GdxBasisUniversal. There are probably more that are not in gdx-liftoff's known extension list. If you can get one of these using an extensions checkbox in Liftoff, that way is strongly recommended.

(There's probably a more elegant way to solve this using Gradle's dependency constraints; I just haven't figured it out yet... If anyone wants to flex their Gradle muscles and provide a way for the old gwt-user and gdx-backend-gwt dependencies to be automatically excluded, that would be very welcome!)

Selecting MOE causes the project to not generate correctly, and errors are logged.

The iOS backend using Multi-OS Engine (MOE) seems to have some incompatibility with the current Gradle, 8.7, that also goes back almost to 8.3. I'm not exactly clear on the nature of the incompatibility, other than it's supposed to be fixed in the next major Gradle release (8.8 or 9.0). Because that won't release for some time, MOE has been temporarily removed from Liftoff 1.12.1.7; it won't work in earlier versions unless you go back to 1.12.0.4 or downgrade Gradle yourself to 8.3. This isn't an outcome I'm happy with, but it should get resolved eventually.

In 1.12.1.8 and later, the default icons for Android projects look terrible!

This is all according to plan. The plan being, you should never be submitting an app to the Google Play Store with any default title, default description, or default icon, because that makes you look like a duplicate of any other app with those default properties. And duplicate apps get suspended for plagiarism! In order to at least avoid ever producing an identical icon, there are roughly 4 billion possible randomized icons that can be generated now. This involves randomly choosing some colors and two icons from OpenMoji, then chopping the icons in half, using a left and a right half, and chucking those icons into the Android app section, all poorly resized except for the hdpi one.

The iOS project doesn't currently use a randomized icon because it hasn't been reported to be a problem there, yet. If it does become a good idea to randomize iOS icons, it won't be hard to make them random, too.

In short, you should really pay attention to your icon when you are submitting to Google Play Store, but in case you don't one time, the awful random icon should not be currently in use by any actual apps.