Correct way to load assets that works for all circumstances

Can I clarify the correct way to load assets, specifically so that during development it loads them from the assets/ folder, and when the game is packaged as a jar, it loads them from the jar itself? The only way I seem to be able to do this is to create a flag to tell the software that it’s running as a jar.

Currently, in my simpleInit() section I have:

		if (Settings.LOAD_FROM_JAR) {
			assetManager.registerLocator("assets/", ClasspathLocator.class);
		} else {
			assetManager.registerLocator("assets/", FileLocator.class);
		}

and then when I come to load an asset, I have:

 game.getAssetManager().loadTexture("Textures/mytex.jpg");

If I want to load a generic resource from the classpath, I seem to need to do:

 InputStream inputStream = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("src/maps/mymap.csv"); // Needs to start with "src"?

This all works, but seems very messy and ad-hoc. Any pointers are much appreciated. Thanks!

Claspath should always work and is always the way that the assets should be loaded. It only fails for people who didn’t setup “their favorite IDE” correctly, I guess.

Basically, during development that ./assets folder needs to be on the classpath.

As for this, again: your project is not setup correctly. You need to set it up to copy resources from src/maps. (Edit: or put resources in the standard location for your build tool.)

Since we don’t know what IDE or build tool you are using, it’s impossible to help further.

Thanks a lot for your help. Sorry, I should have mentioned I use Eclipse.

For future reference, and in case anyone else has the same problem, I just have

		assetManager.registerLocator("assets/", ClasspathLocator.class);

in simpleInit(), and I now load resources as so:

                    Thread.currentThread().getContextClassLoader().getResourceAsStream(filename);

It was just the ClasspathLocator that I didn’t know worked for everything, the rest is pretty obvious with hinsight (I don’t know why I didn’t move my resources to a “data” source folder).

You don’t have to do that. It’s automatic.

Thanks. So basically, if I remove all my code, everything works. :wink:

Yep. It was just a project setup issue all along.

I think there is a guide for Eclipse users on the wiki somewhere.

If using eclipse just put assets under the resources folder (under src–>main–>resources) They will automatically be put on the classpath in development and when jar is built. Also, you don’t need the assets folder at all following this approach.

…and if you change just one line of code you will also have to send all 200 mb of assets to your players again.

if you would use Gradle build, for development to skip build of JAR you can just use:

    runtime files("..//AssetsProject/assets")  

in dependencies

that will just add assets folder without build anything.

another advantage is that you can have assets in separate project (that you can have as ANT project to open in SDK)

1 Like

Not if the game implementation is provided as an osgi bundle :wink:

But you just described an approach where the resources are packed in the same .jar with the classes. Not sure how osgi matters at all in that case.

Yes, resources (assets) and updater/launcher application in one jar using embedded Felix osgi container and game implementation in a bundle installed (and updatable) to the container. Content would still be loaded via classpath.

That sounds like a overly complicated approach. I do not package my assets into my jars. I leave them in a folder. I also use an external updater jar that is capable of updating assets, libraries, and the main jar. Once the main jar is updated, it downloads a new updater jar. The only thing i distribute is the updater jar, and it performs the downloads for everything.

It is also easier to trouble shoot and debug assets when they are loose files. For distribution sometimes I distribute assets in an external zip.

With external files, it works just fine for the asset loader load from an ide or the app.

I personally recommend using IDEA for development with JME, it works nicely with gradle. Just remember that when using gradle with loose assets, do not map the directory with the assets in it as a resource directory.

My project supports fully dynamic assets - the only assets that need to be distributed are the UI assets (which get bundled into the jar as resources). Everything else is downloaded on the fly as needed and cached for later re-use. Coupled with the entity system, this means that you don’t even need to have all assets for a specific area downloaded before you start playing/interacting with that area - although you will see the world in a partially loaded state while assets download unless the developer forces a loading screen until the area is fully loaded.

This type of asset system is pretty complex, however, and not one I’d recommend replicating unless dynamic assets are a must.