Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

Sign up now!

Tutorial Loading and using resources on the bot store

Engineer
Joined
Jul 28, 2013
Messages
2,776
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:
<resources>
        <resource>path/to/file.png</resource>
</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:
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:
<resources>
        <resource>path/to/</resource>
</resources>
 
Last edited:
Joined
Dec 18, 2014
Messages
398
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.
 
Last edited:
Engineer
Joined
Jul 28, 2013
Messages
2,776
Added an example of how to include an entire folder as a resource.
 
Author of MaxiBots
Joined
Dec 3, 2013
Messages
6,863
How would you tell it that the resource is to be stored in the 'Environment.getStorageDirectory()' folder?
 
Engineer
Joined
Jul 28, 2013
Messages
2,776
How would you tell it that the resource is to be stored in the 'Environment.getStorageDirectory()' folder?
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.
 
Author of MaxiBots
Joined
Dec 3, 2013
Messages
6,863
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.
Ah I see, of course. The storage folder would only really be used for local settings. Duh
 
Joined
Jan 8, 2015
Messages
1,427
Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
Java:
if (chatbox != null) {
    g.draw(chatbox, 0, 388, null);
}

Could you help me out @Aidden @Cloud
 
Author of MaxiBots
Joined
Dec 3, 2013
Messages
6,863
Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
Java:
if (chatbox != null) {
    g.draw(chatbox, 0, 388, null);
}

Could you help me out @Aidden @Cloud
Code:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");
Image image = ImageIO.read(chatbox);
 
Joined
Jan 8, 2015
Messages
1,427
you need to wrap it with try/catch

You mean like this?

Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");

private Image getImage() {
    try {
        return ImageIO.read(chatbox);
    } catch (IOException e) {
        return null;
    }
}

@Override
public void onPaint(Graphics2D g) {
    g.drawImage(getImage(), 0, 338, null);
}

Since that's giving me;

Code:
java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(Unknown Source)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.getImage(LazyAIOMiner.java:185)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.onPaint(LazyAIOMiner.java:195)
    at com.runemate.game.api.script.framework.core.EventDispatcher.process(nob:180)
    at app.Ri.paintComponent(rcb:821)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JLayeredPane.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    at java.awt.Container.paint(Unknown Source)
    at java.awt.Window.paint(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
 
Last edited:
Author of MaxiBots
Joined
Dec 3, 2013
Messages
6,863
You mean like this?

Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");

private Image getImage() {
    try {
        return ImageIO.read(chatbox);
    } catch (IOException e) {
        return null;
    }
}

@Override
public void onPaint(Graphics2D g) {
    g.drawImage(getImage(), 0, 338, null);
}

Since that's giving me;

Code:
java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(Unknown Source)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.getImage(LazyAIOMiner.java:185)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.onPaint(LazyAIOMiner.java:195)
    at com.runemate.game.api.script.framework.core.EventDispatcher.process(nob:180)
    at app.Ri.paintComponent(rcb:821)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JLayeredPane.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    at java.awt.Container.paint(Unknown Source)
    at java.awt.Window.paint(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
You're probably loading the resource wrong
 
Author of MaxiBots
Joined
Dec 3, 2013
Messages
6,863
Any suggestions here @Aidden ?
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
 
Joined
Mar 26, 2014
Messages
33
You mean like this?

Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");

private Image getImage() {
    try {
        return ImageIO.read(chatbox);
    } catch (IOException e) {
        return null;
    }
}

@Override
public void onPaint(Graphics2D g) {
    g.drawImage(getImage(), 0, 338, null);
}

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:
import com.runemate.game.api.hybrid.Environment;
import com.runemate.game.api.script.framework.AbstractScript;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.EventListener;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.function.Consumer;

/**
* Author: Tom
* Date: 04/03/2015
* Time: 20:38
*/
public class ImageManager {

    private static final Image NIL_IMAGE = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);

    private final AbstractScript script;
    private final LRUImageCache cache = new LRUImageCache(this);
    private final LinkedList<ImageLoadExceptionEventListener> listeners = new LinkedList<>();

    private int maxImageCount;

    public ImageManager(AbstractScript script, int maxImageCount) {
        this.script = script;
        this.maxImageCount = maxImageCount;
    }

    public ImageManager(AbstractScript script) {
        this(script, -1);
    }

    public final int getMaxImageCount() {
        return maxImageCount;
    }

    public final void setMaxImageCount(int maxImageCount) {
        this.maxImageCount = maxImageCount;
    }

    public final void submitLoadExceptionListener(ImageLoadExceptionEventListener listener) {
        listeners.add(listener);
    }

    public final void removeLoadExceptionListener(ImageLoadExceptionEventListener listener) {
        listeners.remove(listener);
    }

    public final Image get(String path, boolean forceLoad, ImageLoadMode imageLoadMode) {
        String imageTag = imageLoadMode.name().concat(":").concat(path);
        Image image = cache.get(imageTag);
        if (forceLoad || image == null) {
            synchronized (cache) {
                image = cache.get(imageTag);
                if (image == null) {
                    cache.put(imageTag, image = imageLoadMode.get(this, path));
                }
            }
        }
        return image;
    }

    public enum ImageLoadMode {
        RESOURCE() {
            @Override
            Image get(ImageManager instance, String path) {
                try (InputStream stream = instance.script.getClass().getResourceAsStream(path)) {
                    return ImageIO.read(stream);
                } catch (IOException e) {
                    onError(instance, new ImageLoadExceptionEvent(path, this, e));
                }
                return NIL_IMAGE;
            }
        },
        LOCAL_SCRIPT() {
            @Override
            Image get(ImageManager instance, String path) {
                path = Environment.getStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
                try (InputStream stream = new FileInputStream(path)) {
                    return ImageIO.read(stream);
                } catch (IOException e) {
                    onError(instance, new ImageLoadExceptionEvent(path, this, e));
                }
                return NIL_IMAGE;
            }
        },
        LOCAL_GENERAL() {
            @Override
            Image get(ImageManager instance, String path) {
                path = Environment.getGeneralStorageDirectory().getAbsolutePath().concat(File.separator).concat(path);
                try (InputStream stream = new FileInputStream(path)) {
                    return ImageIO.read(stream);
                } catch (IOException e) {
                    onError(instance, new ImageLoadExceptionEvent(path, this, e));
                }
                return NIL_IMAGE;
            }
        };

        abstract Image get(ImageManager instance, String path);

        final void onError(ImageManager manager, final ImageLoadExceptionEvent exception) {
            manager.listeners.forEach(new Consumer<ImageLoadExceptionEventListener>() {
                @Override
                public void accept(ImageLoadExceptionEventListener listener) {
                    listener.onEvent(exception);
                }
            });
        }
    }

    public static interface ImageLoadExceptionEventListener extends EventListener {
        public void onEvent(ImageLoadExceptionEvent event);
    }

    public static final class ImageLoadExceptionEvent {
        private final String path;
        private final ImageLoadMode imageLoadMode;
        private final IOException exception;

        public ImageLoadExceptionEvent(String path, ImageLoadMode imageLoadMode, IOException exception) {
            this.path = path;
            this.imageLoadMode = imageLoadMode;
            this.exception = exception;
        }

        public final String getPath() {
            return path;
        }

        public final ImageLoadMode getImageLoadMode() {
            return imageLoadMode;
        }

        public final IOException getException() {
            return exception;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("IOExceptionEvent{");
            sb.append("path='").append(path).append('\'');
            sb.append(", mode=").append(imageLoadMode.name());
            sb.append(", exception=").append(exception.getMessage());
            sb.append('}');
            return sb.toString();
        }
    }

    private final class LRUImageCache extends LinkedHashMap<String, Image> {

        private final ImageManager manager;

        private LRUImageCache(ImageManager manager) {
            this.manager = manager;
        }

        @Override
        protected final boolean removeEldestEntry(Map.Entry<String, Image> eldest) {
            return manager.maxImageCount == -1 || size() > manager.maxImageCount;
        }
    }
}
 
Joined
Dec 10, 2014
Messages
3,255
You mean like this?

Java:
private final InputStream chatbox = LazyAIOMiner.class.getResourceAsStream("/Resources/chatbox.png");

private Image getImage() {
    try {
        return ImageIO.read(chatbox);
    } catch (IOException e) {
        return null;
    }
}

@Override
public void onPaint(Graphics2D g) {
    g.drawImage(getImage(), 0, 338, null);
}

Since that's giving me;

Code:
java.lang.IllegalArgumentException: input == null!
    at javax.imageio.ImageIO.read(Unknown Source)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.getImage(LazyAIOMiner.java:185)
    at com.runemate.geashawscripts.LazyAIOMiner.LazyAIOMiner.onPaint(LazyAIOMiner.java:195)
    at com.runemate.game.api.script.framework.core.EventDispatcher.process(nob:180)
    at app.Ri.paintComponent(rcb:821)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at javax.swing.JLayeredPane.paint(Unknown Source)
    at javax.swing.JComponent.paintChildren(Unknown Source)
    at javax.swing.JComponent.paintToOffscreen(Unknown Source)
    at javax.swing.RepaintManager.paint(Unknown Source)
    at javax.swing.JComponent.paint(Unknown Source)
    at java.awt.GraphicsCallback$PaintCallback.run(Unknown Source)
    at sun.awt.SunGraphicsCallback.runOneComponent(Unknown Source)
    at sun.awt.SunGraphicsCallback.runComponents(Unknown Source)
    at java.awt.Container.paint(Unknown Source)
    at java.awt.Window.paint(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at javax.swing.RepaintManager$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.paintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.prePaintDirtyRegions(Unknown Source)
    at javax.swing.RepaintManager.access$1300(Unknown Source)
    at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$400(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
try "Resources/chatbox.png" instead of "/Resources/chatbox.npg"

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