Here's my current pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hu.elte.inf</groupId>
<artifactId>ThesisMVN</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>main/Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.javatuples</groupId>
<artifactId>javatuples</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>
I need the structure of my resources folder (and its subfolders) maintained, as currently takes them out of resources folder, so my game can't start because it can't find all the textures.
resource structure within the project
jar-ed resource structure (note that only one effects
folder is in the jar, it put the images next to the class file here)
Here's how I'm currently loading Images
public class ResourceLoader {
public static Image getResource(String path){
Image img=null;
try{
img = ImageIO.read(new File(path));
}
catch(IOException e) {
System.err.println("File not found(" path ')');
e.printStackTrace();
}
return img;
}
}
The path
passed to getResource is acquired from an enum where I set the path of all of my Images, like this:
...
BULLET("src/main/resources/bullet.png"),
BULLET_GREY("src/main/resources/bullet_grey.png"),
...
AOE_SLOW("src/main/resources/effects/aoeSlow.png"),
AOE_DISARM("src/main/resources/effects/aoeDisarm.png"),
...
I assume I should drop the src/main/resources
prefixes, but then I can onyl reach the Images once the project is jarred up.
This may be the wonky part of my setup but I'm currently storing every loaded Image in a class called GameStateData
. Whenever I need to create a new Sprite
I just get the already loaded Image from there, so I only need to load every Image just once when launching the game.
CodePudding user response:
I need the structure of my resources folder (and its subfolders) maintained
It IS maintained. Every file and directory in your resources folder has been dutifully copied straight into the jar as the Standard Directory Layout dictates.
The problem is your setup: At 'dev time' you appear to attempt to load from resources/items/someItem.png
and this doesn't work when your app is jarred up. There are 2 obvious ways this can be happening;
You're confused about the reason
You're trying to use new FileInputStream
, new File
, or otherwise are attempting to load these as files. This does not work and cannot work and no amount of futzing with directory structures will ever make it work. In java, file means file - and a png entry in a jarfile is not itself a file.
The way to load such resources is, always, this strategy:
Pick a class that is the 'source location' - as in, the resource you're looking for will be where-ever the JVM found this class file. Generally you can pick any class in your entire application; this is relevant only when you use modularized class loading systems. If you don't know what that means, you're not using those.
Call
MyContextClass.class.getResource(resourceKey)
to obtain a URL object, which you can then pass to whatever API allows you to do that (and lots of APIs do, notably including swing's ownImageIcon
). Alternatively, usetry (var in = MyContextClass.class.getResourceAsStream(resourceKey) { /* use resource here */ }
- this is the one to use if the API in question doesn't have an overload that takes a URL but does have one that takes an InputStream. This is also the one to use if you want to directly read the contents.resourceKey
comes in 2 flavours. There's"foo/bar.png"
which resolves a path relative to the exact package your context class is in. If you havepackage com.foo; public class Bar {}
then somewhere in the deployment there'scom/foo/Bar.class
. For example, in a jar file, or in abin
dir. If you then writeBar.class.getResource("baz/quux.png")
, and Bar.class was in that jar file, then the system is going to look in the same jar file, forcom/foo/baz/quux.png
. Alternatively, include a leading slash:"/foo/bar.png"
would look in the same jar, but forfoo/bar.png
.That's all you have to do. Build systems and IDEs ensure that you put your images exactly where you have them now (in a
resources
folder), you do not includeresources
in your deployment key (for the same reason you have your java source files insrc/main/java/com/foo/MyApp.class
, and you do not includesrc
,main
, orjava
in your fully qualified class names. It's justcom.foo.MyApp
, notmain.java.com.foo.MyApp
. Theresources
isn't a part of it any more thanjava
is a part of your class names. If it doesn't work you've misconfigured them.
You've got a wonky setup
It's possible you've been hacking away and e.g. using a plugin system where you check for certain files either directly on the filesystem yourself, -OR- load via ContextClass.class.getResource
, or you've been messing with the way your IDE's maven plugin identifies resource directories, or you've been handrolling the setup of your IDE projects (instead of using its maven integration) and marked src/main
as source dir (instead of src/main/java
and src/main/resources
). The setup is broken; fix that (do not 'fix' it by trying to keep resources
around).