Tutorial Loading and using resources on the bot store

Discussion in 'Tutorials & Resources' started by Cloud, Jan 2, 2015.

  1. Hello there, my name is Cloud and I am here to show you an example of how to load a resource from the bot store.

    The first step is to get make sure your resource gets packaged with your bot on the store. To do this you need to add an entry to your manifest.
    Code (Text):
    1. <resources>
    2.         <resource>path/to/file.png</resource>
    3. </resources>
    After you add the entry, you then need to add the code to read it from within the bot. You do this by getting an input stream from the class loader.
    Code (Text):
    1. InputStream in = MainScriptClass.class.getResourceAsStream("/path/to/file.png");
    Note the slash at the beginning of the file path, it's there to indicate that it's an absolute path instead of a relative path.

    Once you have the InputStream, you can then null check it and read from the stream to get the resource's data.


    Edit: You can also include an entire folder as a resource by doing the following:
    Code (Text):
    1. <resources>
    2.         <resource>path/to/</resource>
    3. </resources>
     
    #1 Cloud, Jan 2, 2015
    Last edited: Jan 4, 2015
    Savior and Baddest Man on Earth like this.
  2. I was originally having problems with mine when I followed the above tutorial and used the extension ".web" to store a byte array from a FileWeb. The issue was resolved simply by changing the ".web" extension to the ".bin" extension.

    Apparently the file extension matters. When creating a file with data that doesn't have an established extension, use ".bin". If there is a well-established extension, though, such as ".fxml" for JavaFX UI files or ".png" for image files, you should use those.
     
    #2 Philosobyte, Jan 2, 2015
    Last edited: Jan 2, 2015
  3. Added an example of how to include an entire folder as a resource.
     
  4. Works great with FXML :D Thanks Cloud!
     
  5. How would you tell it that the resource is to be stored in the 'Environment.getStorageDirectory()' folder?
     
  6. You can't, it gets packed into the jar and you load it as a resource like that. The alternative is to download the web and caching it there.
     
  7. Ah I see, of course. The storage folder would only really be used for local settings. Duh
     
  8. Code (Java):
    1. private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
    Code (Java):
    1. if (chatbox != null) {
    2.     g.draw(chatbox, 0, 388, null);
    3. }
    Could you help me out @Aidden @Cloud
     
  9. Code (Text):
    1. private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
    2. Image image = ImageIO.read(chatbox);
     
  10. That's giving me an Unhandled exception (java.io.IOException)
     
  11. you need to wrap it with try/catch
     
  12. You mean like this?

    Code (Java):
    1. private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
    2.  
    3. private Image getImage() {
    4.     try {
    5.         return ImageIO.read(chatbox);
    6.     } catch (IOException e) {
    7.         return null;
    8.     }
    9. }
    10.  
    11. @Override
    12. public void onPaint(Graphics2D g) {
    13.     g.drawImage(getImage(), 0, 338, null);
    14. }
    Since that's giving me;

    Code (Text):
    1. java.lang.IllegalArgumentException: input == null!
    2.     at javax.imageio.ImageIO.read(Unknown Source)
    3.     at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.getImage(LazyAIOMiner.java:185)
    4.     at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.onPaint(LazyAIOMiner.java:195)
    5.     at com.runemate.game.api.script.framework.core.EventDispatcher.process(nob:180)
    6.     at app.Ri.paintComponent(rcb:821)
    7.     at javax.swing.JComponent.paint(Unknown Source)
    8.     at javax.swing.JComponent.paintChildren(Unknown Source)
    9.     at javax.swing.JComponent.paint(Unknown Source)
    10.     at javax.swing.JLayeredPane.paint(Unknown Source)
    11.     at javax.swing.JComponent.paintChildren(Unknown Source)
    12.     at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    13.     at javax.swing.RepaintManager.paint(Unknown Source)
    14.     at javax.swing.JComponent.paint(Unknown Source)
    15.     at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    16.     at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    17.     at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    18.     at java.awt.Container.paint(Unknown Source)
    19.     at java.awt.Window.paint(Unknown Source)
    20.     at javax.swing.RepaintManager$4.run(Unknown Source)
    21.     at javax.swing.RepaintManager$4.run(Unknown Source)
    22.     at java.security.AccessController.doPrivileged(Native Method)
    23.     at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    24.     at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    25.     at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    26.     at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    27.     at javax.swing.RepaintManager.access$1300(Unknown Source)
    28.     at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    29.     at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    30.     at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    31.     at java.awt.EventQueue.access$400(Unknown Source)
    32.     at java.awt.EventQueue$3.run(Unknown Source)
    33.     at java.awt.EventQueue$3.run(Unknown Source)
    34.     at java.security.AccessController.doPrivileged(Native Method)
    35.     at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    36.     at java.awt.EventQueue.dispatchEvent(Unknown Source)
    37.     at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    38.     at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    39.     at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    40.     at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    41.     at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    42.     at java.awt.EventDispatchThread.run(Unknown Source)
     
    #12 Geashaw, Mar 2, 2015
    Last edited: Mar 2, 2015
  13. You're probably loading the resource wrong
     
  14. Any suggestions here @Aidden ?
     
  15. You're using the absolute path so you need the full directory and by the looks of it that's not what you're giving it. Try it without the '/'
    If that doesn't work try specifying the full directory ie /a/b/c/thisscriptpackage/Resources/bla.png
     
  16. Firstly your trying to read the image from the stream every time the graphics are rendered, you also never close the stream which can cause memory issues.

    I've quickly put together a simple image management utility that's something like i would use in a situation with multiple images are being loaded. Look at how the streams are handled and the actual Image objects cached

    Code (Text):
    1. import com.runemate.game.api.hybrid.Environment;
    2. import com.runemate.game.api.script.framework.AbstractScript;
    3.  
    4. import javax.imageio.ImageIO;
    5. import java.awt.*;
    6. import java.awt.image.BufferedImage;
    7. import java.io.File;
    8. import java.io.FileInputStream;
    9. import java.io.IOException;
    10. import java.io.InputStream;
    11. import java.util.EventListener;
    12. import java.util.LinkedHashMap;
    13. import java.util.LinkedList;
    14. import java.util.Map;
    15. import java.util.function.Consumer;
    16.  
    17. /**
    18. * Author: Tom
    19. * Date: 04/03/2015
    20. * Time: 20:38
    21. */
    22. public class ImageManager {
    23.  
    24.     private static final Image NIL_IMAGE = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
    25.  
    26.     private final AbstractScript script;
    27.     private final LRUImageCache cache = new LRUImageCache(this);
    28.     private final LinkedList<ImageLoadExceptionEventListener> listeners = new LinkedList<>();
    29.  
    30.     private int maxImageCount;
    31.  
    32.     public ImageManager(AbstractScript script, int maxImageCount) {
    33.         this.script = script;
    34.         this.maxImageCount = maxImageCount;
    35.     }
    36.  
    37.     public ImageManager(AbstractScript script) {
    38.         this(script, -1);
    39.     }
    40.  
    41.     public final int getMaxImageCount() {
    42.         return maxImageCount;
    43.     }
    44.  
    45.     public final void setMaxImageCount(int maxImageCount) {
    46.         this.maxImageCount = maxImageCount;
    47.     }
    48.  
    49.     public final void submitLoadExceptionListener(ImageLoadExceptionEventListener listener) {
    50.         listeners.add(listener);
    51.     }
    52.  
    53.     public final void removeLoadExceptionListener(ImageLoadExceptionEventListener listener) {
    54.         listeners.remove(listener);
    55.     }
    56.  
    57.     public final Image get(String path, boolean forceLoad, ImageLoadMode imageLoadMode) {
    58.         String imageTag = imageLoadMode.name().concat(":").concat(path);
    59.         Image image = cache.get(imageTag);
    60.         if (forceLoad || image == null) {
    61.             synchronized (cache) {
    62.                 image = cache.get(imageTag);
    63.                 if (image == null) {
    64.                     cache.put(imageTag, image = imageLoadMode.get(this, path));
    65.                 }
    66.             }
    67.         }
    68.         return image;
    69.     }
    70.  
    71.     public enum ImageLoadMode {
    72.         RESOURCE() {
    73.             @Override
    74.             Image get(ImageManager instance, String path) {
    75.                 try (InputStream stream = instance.script.getClass().getResourceAsStream(path)) {
    76.                     return ImageIO.read(stream);
    77.                 } catch (IOException e) {
    78.                     onError(instance, new ImageLoadExceptionEvent(path, this, e));
    79.                 }
    80.                 return NIL_IMAGE;
    81.             }
    82.         },
    83.         LOCAL_SCRIPT() {
    84.             @Override
    85.             Image get(ImageManager instance, String path) {
    86.                 path = Environment.getStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
    87.                 try (InputStream stream = new FileInputStream(path)) {
    88.                     return ImageIO.read(stream);
    89.                 } catch (IOException e) {
    90.                     onError(instance, new ImageLoadExceptionEvent(path, this, e));
    91.                 }
    92.                 return NIL_IMAGE;
    93.             }
    94.         },
    95.         LOCAL_GENERAL() {
    96.             @Override
    97.             Image get(ImageManager instance, String path) {
    98.                 path = Environment.getGeneralStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
    99.                 try (InputStream stream = new FileInputStream(path)) {
    100.                     return ImageIO.read(stream);
    101.                 } catch (IOException e) {
    102.                     onError(instance, new ImageLoadExceptionEvent(path, this, e));
    103.                 }
    104.                 return NIL_IMAGE;
    105.             }
    106.         };
    107.  
    108.         abstract Image get(ImageManager instance, String path);
    109.  
    110.         final void onError(ImageManager manager, final ImageLoadExceptionEvent exception) {
    111.             manager.listeners.forEach(new Consumer<ImageLoadExceptionEventListener>() {
    112.                 @Override
    113.                 public void accept(ImageLoadExceptionEventListener listener) {
    114.                     listener.onEvent(exception);
    115.                 }
    116.             });
    117.         }
    118.     }
    119.  
    120.     public static interface ImageLoadExceptionEventListener extends EventListener {
    121.         public void onEvent(ImageLoadExceptionEvent event);
    122.     }
    123.  
    124.     public static final class ImageLoadExceptionEvent {
    125.         private final String path;
    126.         private final ImageLoadMode imageLoadMode;
    127.         private final IOException exception;
    128.  
    129.         public ImageLoadExceptionEvent(String path, ImageLoadMode imageLoadMode, IOException exception) {
    130.             this.path = path;
    131.             this.imageLoadMode = imageLoadMode;
    132.             this.exception = exception;
    133.         }
    134.  
    135.         public final String getPath() {
    136.             return path;
    137.         }
    138.  
    139.         public final ImageLoadMode getImageLoadMode() {
    140.             return imageLoadMode;
    141.         }
    142.  
    143.         public final IOException getException() {
    144.             return exception;
    145.         }
    146.  
    147.         @Override
    148.         public String toString() {
    149.             final StringBuilder sb = new StringBuilder("IOExceptionEvent{");
    150.             sb.append("path='").append(path).append('\'');
    151.             sb.append(", mode=").append(imageLoadMode.name());
    152.             sb.append(", exception=").append(exception.getMessage());
    153.             sb.append('}');
    154.             return sb.toString();
    155.         }
    156.     }
    157.  
    158.     private final class LRUImageCache extends LinkedHashMap<String, Image> {
    159.  
    160.         private final ImageManager manager;
    161.  
    162.         private LRUImageCache(ImageManager manager) {
    163.             this.manager = manager;
    164.         }
    165.  
    166.         @Override
    167.         protected final boolean removeEldestEntry(Map.Entry<String, Image> eldest) {
    168.             return manager.maxImageCount == -1 || size() > manager.maxImageCount;
    169.         }
    170.     }
    171. }
     
  17. try "Resources/chatbox.png" instead of "/Resources/chatbox.npg"

    Also if Resources is a package, pretty sure convention is lowercase and _ for spaces
     

Share This Page

Loading...