Results 1 to 21 of 21

Thread: Improved RuneScape Classic Loader

  1. #1
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default Improved RuneScape Classic Loader

    Hey guys, a few days ago I found a program someone had made to load RSC directly (found here: http://ww2.sythe.org/showthread.php?p=9879730). This was real convenient and all for quick use, but I wanted more from it, so I upgraded it.

    Source is included in the "source" directory, as well as the original compile.bat and run.bat.

    Executable JAR included in main directory.

    New program features include:
    - File->Exit option just because that's standard
    - World Switching menu (all three classic servers)
    - Screenshots (creates directory automatically upon first use)

    Hope you guys enjoy!

    edit:
    Up to date version has been attached.
    Last edited by Waffle; 11-12-2011 at 05:59 AM.

  2. #2
    Join Date
    Aug 2007
    Location
    Colorado
    Posts
    7,421
    Mentioned
    268 Post(s)
    Quoted
    1442 Post(s)

    Default

    Oo I used to love working with RSC bots back in the day. I wish I had an account I'd surely look into this. Nice job.

    Current projects:
    [ AeroGuardians (GotR minigame), Motherlode Miner, Blast furnace ]

    "I won't fall in your gravity. Open your eyes,
    you're the Earth and I'm the sky..."


  3. #3
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Very nice work.

    I just noticed one thing: you've given every world pretty much the same parameters. IIRC, world 3 uses nodeid 5003 and world 1 uses nodeid 5001 and has a different servertype. If you're connecting to world 3 with nodeid 5002 it's potentially very easy for Jagex to detect you're not playing the game the "official" way.

    Eventually I'll add a parser to my loader so that it loads the Javascript from Jagex's servers directly, which will hopefully eliminate that problem.

  4. #4
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    ^ Could you go into a little more detail as to why that's a problem and potentially how to fix it?

    I didn't do any of the actual Applet loading, that was all pre-existing. Everything I did pretty much didn't have anything to do with applet loading., i.e. the menus and taking screenshots.

  5. #5
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    I made the loader using this file. Notice that it's stored on World 2. Take a look at the parameters in that file and compare them to the parameters that the loader uses.

    Jagex's Javascript:

    Code:
    document.write('<param name=nodeid value=5002>');
    document.write('<param name=servertype value=1>');
    The parameters used by the loader:

    Code:
    parameters.put("nodeid", "5002");
    parameters.put("servertype", "1");
    Now, let's take a look at the same Javascript file but from classic1.runescape.com instead of classic2.runescape.com:

    Code:
    document.write('<param name=nodeid value=5001>');
    document.write('<param name=servertype value=3>');
    Notice how the nodeid is 5001 and the servertype is 3. The loader, when you point it at classic1.runescape.com is still using servertype 1 and nodeid 5002. These commands are then passed on to the client. It's impossible to have a servertype of 1 and nodeid of 5002 when connecting to World 1 through the official classic client.

    Instead of loading the same parameters for every single world, it is much safer to either parse the Javascript file or do something like this:

    Code:
    if (world == 1) {
    	parameters.put("nodeid", "5001");
    	parameters.put("servertype", "3");
    } else if (world == 3) {
    	parameters.put("nodeid", "5003");
    	parameters.put("servertype", "1");
    } else {
    	parameters.put("nodeid", "5002");
    	parameters.put("servertype", "1");
    }

  6. #6
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    I noticed the unsigned URL has a reference to the server number as well. I went ahead and changed that, too. Here's the updated parameters code:

    Code:
    if (world.contains("1")
    {
    	parameters.put("unsignedurl","http://www.runescape.com/classicapplet/classicgame.ws?f=1&j=1&a=1");
    	parameters.put("nodeid", "5001");
    	parameters.put("servertype", "1");
    }
    else if (world.contains("3")
    {
    	parameters.put("unsignedurl","http://www.runescape.com/classicapplet/classicgame.ws?f=3&j=1&a=1");
    	parameters.put("nodeid", "5003");
    	parameters.put("servertype", "3");
    }
    else
    {
    	parameters.put("unsignedurl","http://www.runescape.com/classicapplet/classicgame.ws?f=2&j=1&a=1");
    	parameters.put("nodeid", "5002");
    	parameters.put("servertype", "2");
    }
    I suppose I could create a method to do this based off a given world, just to cut down on repeat code. I'll work on that now.

    edit:
    Also, I was getting a NullPointerException, I guess because I didn't have "world" initialized until the main() method. If I set the world to 2 in the field declarations, will the parameters still set correctly when I switch worlds?

    edit2:
    Method for setting correct world parameters:
    Code:
    public static void setWorldParameters(String w)
    {
    	parameters.put("unsignedurl","http://www.runescape.com/classicapplet/classicgame.ws?f=" + w + "&j=1&a=1");
    	parameters.put("nodeid", "500" + w);
    	parameters.put("servertype", w);	
    }
    Then the updated static block:
    Code:
    static
    {
    	parameters = new HashMap<String, String>();
    	setWorldParameters(world);
    	parameters.put("crashurl", "error_loader_crash.ws?a=0&j=1");
    	parameters.put("cabbase", "loader.cab");
    	parameters.put("java_arguments", "-Xmx96m -Dsun.java2d.noddraw=true");
    	parameters.put("country", "0");
    	parameters.put("haveie6", "0");
    	parameters.put("affid", "0");
    	parameters.put("js", "1");
    	parameters.put("objecttag", "0");
    	parameters.put("advertsuppressed", "1");
    	parameters.put("modewhat", "0");
    	parameters.put("modewhere", "0");
    	parameters.put("settings", "wwGlrZHF5gKN6D3mDdihco3oPeYN2KFybL9hUUFqOvk");
    }
    My question about initializing the world and setting it to 2 in the field declarations still remains though
    Last edited by Waffle; 11-08-2011 at 04:16 PM.

  7. #7
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Yep, as long as it loads the parameters after the string 'world' is updated to a new number it should work fine. Test it by loading World 1, it should give an additional message on the "Click here to log in" screen (something like "You need a veterans account to access this world"). If it does, it's working correctly.

  8. #8
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Quote Originally Posted by _sw View Post
    Yep, as long as it loads the parameters after the string 'world' is updated to a new number it should work fine. Test it by loading World 1, it should give an additional message on the "Click here to log in" screen (something like "You need a veterans account to access this world"). If it does, it's working correctly.
    It was doing that when I was loading the incorrect parameters though.

    Does the code I have now update parameters upon switching worlds? I don't really know how to tell.

  9. #9
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    The right client is how it should look when loading World 1:

    http://i.imgur.com/JyZuv.png
    Last edited by _sw; 11-08-2011 at 04:29 PM. Reason: Large image broke this post :P

  10. #10
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Mine doesn't even display a members' message. Uh oh

    edit:
    Now it says Veteran account is needed on the default startup, even though it's loading world 2. Lol..
    Last edited by Waffle; 11-08-2011 at 04:36 PM.

  11. #11
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Haha. I'll add the nodeid, unsignedurl and servertype changes to your version of the loader. Will get back to you.

  12. #12
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Actually, I snooped around in all 3 servers' page source codes, and looked at the parameters for all three.

    I was assuming all three parameters were different for every world, but they aren't. Some are the same for worlds 2 and 3, which makes sense now that I think about it because they don't require a veteran account whereas world 1 does.

    Also, the settings string has changed. Recommend I update that?

    edit:
    Servers 2 and 3 have server type 1. Server 1 has server type 3. /facepalm Jagex for making sense

    edit2:
    So here we go:
    Code:
    public static void setWorldParameters(String w)
    {
    	parameters.put("unsignedurl","http://www.runescape.com/classicapplet/classicgame.ws?f=" + w + "&j=1&a=1");
    	parameters.put("nodeid", "500" + w);
    	
    	if (w.contains("1"))
    		parameters.put("servertype", "3");
    	else
    		parameters.put("servertype", "1");
    }
    Last edited by Waffle; 11-08-2011 at 04:51 PM.

  13. #13
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Edit: Okay, it's very strange. No matter what with your loader - I always either get JUST the Veteran's message no matter what world I select, or never get it even if World 1 is selected.

    I've modified my loader (very roughly) to have multiple world support. It uses arguments, so to play in World 1 you run it as "start javaw -Xmx128m RSCLoader 1" etc. It seems to work okay. Presumably the problem is that it's not loading the params correctly when switching worlds.

    http://pastebin.com/fwkTy29U
    Last edited by _sw; 11-08-2011 at 04:59 PM.

  14. #14
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Now I am getting the members' message as normal, but World 1 doesn't display the Veteran message.

    Does this mean parameters are not updating upon switching worlds?

    edit:
    Duh, stupid me. Problem fixed. I called the setWorldParameters() method in the switchWorld() method.

    Works like a charm now. I'll add the updated program to the first post as well as this one.
    Last edited by Waffle; 11-08-2011 at 04:59 PM.

  15. #15
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Great.

    Speaking of the "settings" parameter... I have no idea what it does. It seems to change completely randomly. Having two completely different IP addresses and computers load the same settings would definitely be suspicious, which is why it's infinitely safer to parse the plugin.js file for parameters. That's what all of the public bots made since the 2009 update have done. APOS, Reflectionist, ARS, Pro-Bot, RSCBot, etc.

  16. #16
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    ^ Then let's do that. Recommended approach? I was thinking just using a BufferedReader or something similar to what someone would use to grab HiScores Lite data

  17. #17
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Take a look at how Reflectionist does it:

    http://rscc.dyndns.info/rsc/SourceCo...lectionist.rar

    (src/org/meatstick/reflectionist/loader)

    JarLoader.java
    RSApplet.java
    RSAppletStub.java

    Reflection in Reflectionist hasn't worked for about a year, but the loader part still works perfectly.

  18. #18
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    ^ You're going to have to explain to me where it's grabbing the settings because I looked over it for about 5 mins and couldn't figure it out. I have to go to class from now until about 3 hours from now, so I will be mostly unable to reply and work on my program til then.

    Thanks for your help so far, btw. My end goal is to create something similar to SMART for RSC that still works with SCAR. But I still have lots of step-by-step learning to do before I get there.

  19. #19
    Join Date
    Aug 2011
    Posts
    33
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    
    package org.meatstick.reflectionist.web;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.logging.Level;
    import java.util.logging.Logger;
    
    /**
     *
     * @author Lukas
     */
    public class WebCrawler {
    
        public WebCrawler() {
        }
    
        public static Map getParameters() {
            try {
                BufferedReader br = openCon("http://classic2.runescape.com/plugin.js?param=o0,a0,s0");
                HashMap map = new HashMap();
                String s;
                while((s = br.readLine()) != null) {
                    if(!s.contains("param name") || !s.contains("value")) {
                        continue;
                    }
                    s = s.replace("(", "");
                    s = s.replace(")", "");
                    s = s.replaceAll("document.write", "").replaceAll("\"", "").replaceAll("'", "").replaceAll("<", "").replaceAll(">", "").replaceAll(";", "");
                    String param_name = null;
                    String value = null;
                    if(s.indexOf("param name") != -1 && s.indexOf("value") != -1) {
                        if(s.contains("unsignedurl")) {
                            System.out.println(s);
                        }
                        param_name = s.trim().substring("param_name=".length(), s.indexOf("value") - 2);
                        s = s.substring(s.indexOf(param_name) + (param_name.length() + 1), s.length());
                        
                        value = s.trim().substring("value=".length(), s.length());
                        if(param_name.contains("unsignedurl")) {
                            System.out.println("val"+value);
                            System.out.println("prm"+param_name);
                        }
                        map.put(param_name, value);
                    }
                }
                if(map.containsKey("haveie6")) {
                    map.remove("haveie6");
                }
                map.put("haveie6", "0");
                return map;
            } catch (Exception ex) {
                Logger.getLogger(WebCrawler.class.getName()).log(Level.SEVERE, null, ex);
                System.exit(0);
            }
            return null;
        }
    
        public static BufferedReader openCon(String url) throws Exception{
    		return new BufferedReader(
    			new InputStreamReader(
    				new URL(url).openStream()));
        }
    
    
    }

  20. #20
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    Wow. Exactly what I had in mind!

  21. #21
    Join Date
    Nov 2011
    Posts
    41
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    The WebCrawler() class you posted set some parameters with strings that were a character or two too short. I fixed that, and made it set the "haveie6" parameter only once at the end of the while loop.

    Code:
    public static void parseForSettings(String w)
    {
    	System.out.println("\n"); //For debugging use
    	try
    	{
    		URL url = new URL("http://classic" + w + ".runescape.com/plugin.js?param=o0,a0,s0");
    		BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
    			
    		String raw;
    	 
    		while((raw = br.readLine()) != null)
    		{
    			if(!raw.contains("param name") || !raw.contains("value") || raw.contains("haveie6"))
    				continue;
    			
    			raw = raw.replace("(", "");
    			raw = raw.replace(")", "");
    			raw = raw.replaceAll("document.write", "").replaceAll("\"", "").replaceAll("'", "").replaceAll("<", "").replaceAll(">", "").replaceAll(";", "");
    			
    			String param_name = null;
    			String value = null;
    			
    			if(raw.indexOf("param name") != -1 && raw.indexOf("value") != -1)
    			{
    				if (raw.contains("error_loader_crash") || raw.contains("http://www.runescape.com/classicapplet/")) //This is where the issue was, we needed to take a substring one character shorter for the crashurl and unsigned applet parameters
    					param_name = raw.trim().substring("param_name=".length(), raw.indexOf("value") - 3);
    				else
    					param_name = raw.trim().substring("param_name=".length(), raw.indexOf("value") - 2);
    					
    				raw = raw.substring(raw.indexOf(param_name) + (param_name.length() + 1), raw.length());
    				
    				value = raw.trim().substring("value=".length(), raw.length());
    				
    				System.out.println(param_name + ", " + value); //For debugging use (this is how I knew some names weren't correct)
    				parameters.put(param_name, value);
    			}
    		}
    		parameters.put("haveie6", "0"); //Set this parameter once as opposed to every time the while loop executes..
    		System.out.println("haveie6, 0");
    	} catch (Exception ex)
    	{
    		throw new RuntimeException(ex);
    	}
    	System.out.println("\n"); //For debugging use
    }
    Last edited by Waffle; 11-09-2011 at 12:16 AM.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •