Getting null pointer trying to load texture with LWJGL 3 w/ runnable jar

I’m using

ByteBuffer data = stbi_load(file, width, height, comp, 4);

to put my png files into the game but when I create a runnable jar the app can’t find my files.

The structure is like this


Project {
	src {
		Artist {
			Texture(String file) {
				// passing   "./Resources/texture/mytexture.png"
				ByteBuffer data = stbi_load(file, width, height, comp, 4);
			}
		}
	}

	Resources { // this is included as a source folder in the build path
		texture {
			mytexture.png
		}
		
	}		

}


the files will load when I launch from eclipse but not from a runnable jar :frowning:

EDIT:

Found this

For now I’m loading them in as BufferedImages via ImageIO.read(getClass().getResourceAsStream(file)) method call

I had the same problem and it was because my file was actually named file.PNG, and the code was searching for file.png. It worked fine in Eclipse but didn’t work as a runnable jar.

I wish that were my problem but it’s not it. I did get struck by that problem long ago though so I feel your pain.

EDIT: Found a solution which is in the OP.

Your resources folder should be right next to the runnable jar. Unless you package the resources inside the jar for reading, you will need to open the stream directly to resources/image.png.

If you want to reference things from the actual jar, you will need to use getResourceAsStream().

I would recommend packaging a resources folder next to the jar. Instead of using getResourceAsStream() then, you would open it in a new stream.

Example:


File file = new File("resources/image.png");
FileInputStream fis = new FileInputStream(file);

Also, I recommend using PNGDecoder by TWL, but here shows how to use it briefly. I would recommend getting the source file for it. It is licensed, though, so make sure to read it. I am not a fan of ImageIO.
Hey you can use my XMI file format and loader too :^) see my github for it

@Hydroque

What’s the benefit of placing the res folder alongside the jar?

Seems like distribution is better suited for packaging everything into one executable file.

Do you plan to distribute your game as a single JAR despite the known limitations?

It would appear the limitations are unknown to me.

I thought one jar could be wrapped with lauch4j to create a .exe file and the mac has something similar to create an app file from a jar

May depend on the distribution channel. Steam for example does not provide any elaborate diff mechanism, but only checks for file modifications between revisions. If you pack everything into one big JAR file, customers will have to pretty much download the whole game each time, even if you don’t change much.

For our previous game it’s been a ~34 MB download already for small bug fixes, even though the JAR is only about 7 MB (I don’t know what kind of book-keeping or additional stuff they merge into these patches). With all assets packed into the JAR this would have been easily increased to about 200-300 MB.

[quote=“ndnwarrior15,post:1,topic:57495”]
The stbi_load function only works with plain image files on a filesystem. It knows nothing about the classpath and JAR files. If you really want to pack images in JARs, you’ll have to do your own IO and then use stbi_load_from_memory instead.

[quote=“ndnwarrior15,post:1,topic:57495”]
This completely defeats the point of using stb for image IO. The LWJGL demos provide a (simple, not production-ready) method for loading resources, here. It returns a ByteBuffer with the resource contents and it works with both plain files and resources on the classpath.

Based off what CoDi^R said it makes sense to keep the code and resources separate.

But let’s say I have some music (or even images) that I don’t want users simply able to grab and dump into their music library. How are the resources protected from a simple copy + paste?

Java isn’t a language that you protect assets with. In any language, its nearly impossible to keep your assets from the open. You can always access your ram and rip it.

You do not want to use a single jar. One reason is you can’t write to the jar in use. You will have to create two jars, which, obviously, is a bad solution. Using two jars would counter this, but there is nothing better than keeping your assets in a inflate/deflate method file. For example, my XM File series is meant to have everything uncompressed by default. Come load time, everything was stored in XMP files, which are as I described. This allows you to keep your assets nice and tightly packed.

I know a lot of games to use this method. One of them is Gunz: The Duel.

There are many ways to obfuscate. This won’t stop anyone seriously trying, of course, so keep in mind there is a tradeoff. At some point it’s simply not worth your time & effort.

You can put resources into separate JAR(s), and adjust your classpath.

You can wrap your assets in, or convert them to a custom file format.

One project I worked on used ZIP archives with a modified (corrupted) header, renamed to .PAK or something (it didn’t take long for users to figure that out).

If you control the loader code, you can do even more crazy stuff, like simple binary obfuscation with bit-rotations and/or XOR masking. Just don’t call it encryption, please.