Jump to content
Frequently Asked Questions
  • Are you not able to open the client? Try following our getting started guide
  • Still not working? Try downloading and running JarFix
  • Help! My bot doesn't do anything! Enable fresh start in client settings and restart the client
  • How to purchase with PayPal/OSRS/Crypto gold? You can purchase vouchers from other users
  • JDA (Discord API Wrapper) - Dreambot Doesn't Show Local Script When Extending JDA ListenerAdapter Class


    Robosoldier2

    Recommended Posts

    Hey guys,

    So for background, I've got a script that was built using the recommended setup tutorial in the Dreambot docs. All works well: build the artifact into Dreambot folder, client sees script, click to run, voila.

    I was looking to integrate Discord into my project. I picked out the JDA (Java Discord API) from a few options as the wrapper to use. Setup is straight forward; maven, gradle, or import the jar with dependancies as a library manually. I did the latter as I'm not familiar with maven or gradle quite yet — new to Java and all.

    This is where things go funny. I put together the class based on a sample provided on their Github, just to verify it's working. All of the imports are found fine, and the code has no errors. I can run the class directly via the project by right clicking on it, and it connects in fine. I performed some tests with some prints of messages being received. Also works in a standalone program.

    However, when I try to use the below in my bot program, the artifact I build succeeds, but cannot be picked up by Dreambot. This before I've added any interaction from the bot script (no Bot objects instantiated etc).

    I did a bit of trial and error and tracked the cause to the extension of the ListenerAdapter class. As said it has no problems in standalone programs, or running the class alone within the project. However the Dreambot client doesn't pick up the produced jar so long as this class is being extended. But building does succeed as mentioned. If I remove the extension of ListenerAdapter, and the @Override declaration (given no extension), it then picks up the jar fine on the script selection window. I can also extend other classes in this class just fine and it remains visible.

    I welcome any advice. I'm on the novice side when it comes to Java, and Dreambot is a black-box to me in regards to what it does to determine scripts are good to run.

    If wanting to reference the library I'm using:

    https://github.com/DV8FromTheWorld/JDA

    And below is the version in use (this is a link to the latest jar with dependencies (5.0.0-alpha.11):

    https://github.com/DV8FromTheWorld/JDA/releases/download/v5.0.0-alpha.11/JDA-5.0.0-alpha.11-withDependencies.jar

    Thanks all,

    Robo

    import net.dv8tion.jda.api.JDA;
    import net.dv8tion.jda.api.JDABuilder;
    import net.dv8tion.jda.api.entities.ChannelType;
    import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
    import net.dv8tion.jda.api.hooks.ListenerAdapter;
    import javax.security.auth.login.LoginException;
    
    public class Bot extends ListenerAdapter
    {
        public static void main(String[] args)
                throws LoginException
        {
            JDA jda = JDABuilder.createDefault("token").build();
            //You can also add event listeners to the already built JDA instance
            // Note that some events may not be received if the listener is added after calling build()
            // This includes events such as the ReadyEvent
            jda.addEventListener(new Bot());
        }
    
        @Override
        public void onMessageReceived(MessageReceivedEvent event)
        {
    
        }
    }

     

    Edited by Robosoldier2
    Link to comment
    Share on other sites

    1 hour ago, Pandemic said:

    In order for the client to recognize it as a script that can run, one class must extend AbstractScript and have a ScriptManifest annotation :)

    Hey thanks @Pandemic. What you've said makes sense and is how I have it set up per the guides. When I remove the extension of ListenerAdapter on my dedicated Discord class, the artifact builds and is picked up by Dreambot fine. It's only when I build with the extension active that it doesn't show up as a script choice. This all without touching my first class with the extension of AbstractScript and annotation of ScriptManifest.

    Any clues? I can share additional info that you think might help.

    Edited by Robosoldier2
    Link to comment
    Share on other sites

    28 minutes ago, Robosoldier2 said:

    Hey thanks @Pandemic. What you've said makes sense and is how I have it set up per the guides. When I remove the extension of ListenerAdapter on my dedicated Discord class, the artifact builds and is picked up by Dreambot fine. It's only when I build with the extension active that it doesn't show up as a script choice. This all without touching my first class with the extension of AbstractScript and annotation of ScriptManifest.

    Any clues? I can share additional info that you think might help.

    Gotcha then it's most likely a loading issue, it should be printing an error in the console (CTRL+L or press the message in the bottom left of the client) when you open the script manager. Most likely you aren't including the dependencies in your final output artifact.

    Link to comment
    Share on other sites

    7 minutes ago, Pandemic said:

    Gotcha then it's most likely a loading issue, it should be printing an error in the console (CTRL+L or press the message in the bottom left of the client) when you open the script manager. Most likely you aren't including the dependencies in your final output artifact.

    You're bloody absolutely right! And I don't know why I hadn't thought of checking the console for errors... foolish me.

    It is failing to find the ListenerAdapter class as you guessed. Given it runs within the project using the jar I imported, it must be how I'm building it which is causing the problem. Appreciate the nudge in the right direction @Pandemic, and now one I'll need to wrap my head around.

        java.lang.NoClassDefFoundError: net/dv8tion/jda/api/hooks/ListenerAdapter
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)

     

    Link to comment
    Share on other sites

    Hey @Pandemic. Sorry if the tag notifies you,  just afraid this thread would be buried by now, and you clearly know your stuff. Hoping you can lend a hand again...

    Things are going well and I'm able to receive messages via the overriden onMessageReceived event. What I have noticed though is that when I stop scripts executing via Dreambot, it's as if the object I created for the discord event listener and the overriden onMessageReceived function stay in tact. By this I mean, the original connection and object still exists and continues to run, and will receive messages and print them to console. If I start and stop it again, another one spawns. So on and so forth, causing duplication.

    I expected when stopping the script, that it would kill execution and discard any references to the object. Any clues on why this doesn't happen? And if so, how I should best perform clean-up of it on script stopping to prevent duplication of the handler?

    I instantiate the bot within the class scope. Then, within the loop I check if setup has been performed. If not, it's performed, which is essentially the logging in with a token etc.

    Warning: Might not be the nicest code, nor best practice. Bit of a Java learning exercise, along with Dreambot behaviors. I've also stripped out some unrelated code.

    Main class:

        @ScriptManifest(name = "Runescape Testing", description = "Fantastic levels of testing!", author = "H",
                version = 1.0, category = Category.WOODCUTTING, image = "")
        public class TestScript extends AbstractScript implements ChatListener {
    
        private Bot bot = new Bot();
    
        @Override
        public int onLoop() {
    
            if (!bot.GetSetupPerformed()) {
                try {
                    bot.setup();
                } catch (LoginException e) {
                    throw new RuntimeException(e);
                }
            }
            return 1000;
        }

    Discord bot class:

    public class Bot extends ListenerAdapter
    {
        private String newDiscordMessage = "empty";
        private JDA jda;
        private Boolean setupPerformed = false;
        
        public static void main(String[] args) {
    
        }
    
        public void setup() throws LoginException {
            this.jda = JDABuilder.createDefault("<redacted>").build();
            this.jda.addEventListener(new Bot());
            MethodProvider.log("Discord bot setup performed");
            this.setupPerformed = true;
        }
    
        public Bot() {
    
        }
    
        public boolean GetSetupPerformed() {
            return this.setupPerformed;
        }
    
        @Override
        public void onMessageReceived(MessageReceivedEvent event) {
            MethodProvider.log("Event tripped");
            if (event.isFromType(ChannelType.PRIVATE)) {
                MethodProvider.log(String.format("[PM] %s: %s\n", event.getAuthor().getName(), event.getMessage().getContentDisplay()));
            } else {
                MethodProvider.log(String.format("[%s][%s] %s: %s\n", event.getGuild().getName(), event.getTextChannel().getName(), event.getMember().getEffectiveName(), event.getMessage().getContentDisplay()));
            }
        }
        
        public String getReceivedMessage() {
            MethodProvider.log("Received message (in return function): " + this.newDiscordMessage);
            return this.newDiscordMessage;
        }
    }

     

    Thanks in advance!

    Edited by Robosoldier2
    Link to comment
    Share on other sites

    9 minutes ago, Robosoldier2 said:

    Hey @Pandemic. Sorry if the tag notifies you,  just afraid this thread would be buried by now, and you clearly know your stuff. Hoping you can lend a hand again...

    Things are going well and I'm able to receive messages via the overriden onMessageReceived event. What I have noticed though is that when I stop scripts executing via Dreambot, it's as if the object I created for the discord event listener and the overriden onMessageReceived function stay in tact. By this I mean, the original connection and object still exists and continues to run, and will receive messages and print them to console. If I start and stop it again, another one spawns. So on and so forth.

    I expected when stopping the script, that it would kill execution and discard any references to the object. Any clues on why this doesn't happen? And if so, how I should best perform clean-up of it on script stopping to prevent duplication of the handler?

    I instantiate the bot within the class scope. Then, within the loop I check if setup has been performed. If not, it's performed, which is essentially the logging in with a token etc.

    Warning: Might not be the nicest code, nor best practice. Bit of a Java learning exercise, along with Dreambot behaviors. I've also stripped out some unrelated code.

    Main class:

        @ScriptManifest(name = "Runescape Testing", description = "Fantastic levels of testing!", author = "H",
                version = 1.0, category = Category.WOODCUTTING, image = "")
        public class TestScript extends AbstractScript implements ChatListener {
    
        private Bot bot = new Bot();
    
        @Override
        public int onLoop() {
    
            if (!bot.GetSetupPerformed()) {
                try {
                    bot.setup();
                } catch (LoginException e) {
                    throw new RuntimeException(e);
                }
            }
            return 1000;
        }

    Discord bot class:

    public class Bot extends ListenerAdapter
    {
        private String newDiscordMessage = "empty";
        private JDA jda;
        private Boolean setupPerformed = false;
        
        public static void main(String[] args) {
    
        }
    
        public void setup() throws LoginException {
            this.jda = JDABuilder.createDefault("<redacted>").build();
            this.jda.addEventListener(new Bot());
            MethodProvider.log("Discord bot setup performed");
            this.setupPerformed = true;
        }
    
        public Bot() {
    
        }
    
        public boolean GetSetupPerformed() {
            return this.setupPerformed;
        }
    
        @Override
        public void onMessageReceived(MessageReceivedEvent event) {
            MethodProvider.log("Event tripped");
            if (event.isFromType(ChannelType.PRIVATE)) {
                MethodProvider.log(String.format("[PM] %s: %s\n", event.getAuthor().getName(), event.getMessage().getContentDisplay()));
            } else {
                MethodProvider.log(String.format("[%s][%s] %s: %s\n", event.getGuild().getName(), event.getTextChannel().getName(), event.getMember().getEffectiveName(), event.getMessage().getContentDisplay()));
            }
        }
        
        public String getReceivedMessage() {
            MethodProvider.log("Received message (in return function): " + this.newDiscordMessage);
            return this.newDiscordMessage;
        }
    }

     

    Thanks in advance!

    Glad to hear it's working :)

    As to your new issue, we only kill the script thread, not any extra that are spawned by the script itself so you'd need to manually clean those up in the onExit of your script.

    I'm not sure about the library in question but surely it has some methods to close/cleanup/dispose to stop listening, hope that helps!

    Link to comment
    Share on other sites

    Just now, Pandemic said:

    Glad to hear it's working :)

    As to your new issue, we only kill the script thread, not any extra that are spawned by the script itself so you'd need to manually clean those up in the onExit of your script.

    I'm not sure about the library in question but surely it has some methods to close/cleanup/dispose to stop listening, hope that helps!

    Ah fantastic, I hadn't come across the onExit() and wondered if something like that existed. That's perfect. Agree that the library should have some close down functions, will check it out tomorrow.

    Thanks again for the help, and appreciate the quick reply @Pandemic!

    Link to comment
    Share on other sites

    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now
    ×
    ×
    • Create New...

    Important Information

    We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.