Loading an image from .jar

  • Did anybody find a way to load an image from the plug-in .jar?


    Background:
    A) The ImageInformation constructors accept either a File or a String.


    B) Class.gerResourceAsStream(String path) returns an InputStream and I found no (reasonably fool-proof) way to obtain a File from an InputStream


    C) Class.getResource(String path) return an URL, which can be converted to a URI and from this a File. So this seemed the way to go.


    However the following code fails:


    Code
    URL url = PlanksAndBeams.plugin.getClass().getResource("/assets/0.png");
    URI uri = url.toURI();
    File file = new File(uri);
    ImageInformation ii = new ImageInformation(file);

    It crashes in line 3 with the error: java.lang.IllegalArgumentException: URI is not hierarchical in new File(uri);


    Just for information:
    *) url.path = file:/home/mmg/.local/share/Steam/steamapps/common/RisingWorldDedicatedServer/plugins/pnb/pnb.jar!/assets/0.png
    *) uri.string = jar:file:/home/mmg/.local/share/Steam/steamapps/common/RisingWorldDedicatedServer/plugins/pnb/pnb.jar!/assets/0.png
    *) url.protocol = "jar"
    *) uri.scheme = "jar"
    *) and, yes, the .jar file contains the "/assets/0.png" file.


    (I would expect the path to start with "file:///", i.e. 3 slashes, bu maybe it does not matter)


    Anyone has any suggestion? Thanks!

  • Well, converting a resource to a file is tricky. Basically the file doesn't really exist, since it's part of the jar (the OS treats the jar as a single file).
    Usually you would load a resource by using the getResourceAsStream(), which returns an InputStream. However, unfortunately there is currently no way to turn it into an "ImageInformation" or "ModelInformation" object (well, ofc you could store your resource as a file, and then load the file, but that's crap).


    I guess we will add a new constructor to ImageInformation/ModelInformation which accepts an InputStream. Maybe we will also add a convenient way to load a resource directly. I hope we get that ready for the next update ;)

  • This should be implemented after the last update, but I seem unable to make it to work.


    According to the documentation for net.risingworld.api.utils.ImageInformation

    Code
    Example: Load image "Banner.jpg" from jar file (in package rw.plugin.images)
    ImageInformation info = new ImageInformation("/rw/plugin/images/Banner.jpg");

    I have placed an image in the top-level folder resources of the .jar (the same folder where the plugin.yml file is located), but
    new ImageInformation("/resources/plus.png"); always returns an empty image.


    I tried with and without the leading slash and I checked that the .png is indeed in the .jar in the intended folder. What am I doing wrong?

  • Thanks for bringing this up! It looks like the classloader isn't able to find the resources in the jar file... sorry for the inconvenience, we will fix this issue with the next update! :)
    However, you also made me aware of another potential issue: If multiple plugins have an image called "plus.png" in the "resources" folder, it's nearly impossible to determine which "plus.png" image you're actually referring to (since all plugin jars are in the classpath). Even though it is possible to find out the caller class (by using dark voodoo magic and calling internal proprietary API methods), I think it's much cleaner to provide a reference to the actual plugin class in the constructer. Something like that:

    Java
    //If ImageInformation is created in your plugin class
    ImageInformation info = new ImageInformation(this, "/resources/plus.png");
  • Thanks for bringing this up! It looks like the classloader isn't able to find the resources in the jar file... sorry for the inconvenience, we will fix this issue with the next update! :)

    Thanks!

    However, you also made me aware of another potential issue: [...] I think it's much cleaner to provide a reference to the actual plugin class in the constructer. Something like that:

    Java
    //If ImageInformation is created in your plugin class
    ImageInformation info = new ImageInformation(this, "/resources/plus.png");

    Neat! ^^

Participate now!

Don’t have an account yet? Create a new account now and be part of our community!