Oldschool Runescape downloadable client world list mod

March 10th, 2013 by Silabsoft

This mod allows you to never have a “Full” world on the worldlist. setup is simple and does not Modify anything in the gameclient so should be safe to use.

All you have to do is Follow the offical client setup tutorial:

However when it says to use: http://oldschool.runescape.com/jav_config.ws

Replace with: http://silabsoft.org/jav_config.ws

Then enjoy never having to deal with the “Full” message on the worldlist again.

ZRlO1jv Oldschool Runescape downloadable client world list mod

Simple Oldschool Runescape worldlist grabber

March 6th, 2013 by Silabsoft

This is a simple Java application that grabs the Runescape wordlist data the same way the client does.

HoustCountry.java:

/**
 *
 * @author Silabsoft
 */
public enum HostCountry {
 
    USA,
    UK,
    GERMANY,
    UNKNOWN;
 
    public static HostCountry getHostCountry(int countryId) {
        switch (countryId) {
            case 0:
                return HostCountry.USA;
            case 1:
                return HostCountry.UK;
            case 7:
                return HostCountry.GERMANY;
            default:
                return HostCountry.UNKNOWN;
        }
    }
}

ByteStream.java:

/**
 *
 * @author Silabsoft
 */
public class ByteStream {
 
    private ByteStream() {
    }
 
    public ByteStream(byte abyte0[]) {
        data = abyte0;
        caret = 0;
    }
 
    public int g1() {
        return data[caret++] & 0xff;
    }
 
    public byte g1b() {
        return data[caret++];
    }
 
    public int g2() {
        caret += 2;
        return ((data[caret - 2] & 0xff) << 8) + (data[caret - 1] & 0xff);
    }
 
    public int g2b() {
        caret += 2;
        int i = ((data[caret - 2] & 0xff) << 8) + (data[caret - 1] & 0xff);
        if (i > 32767) {
            i -= 0x10000;
        }
        return i;
    }
 
    public int g3() {
        caret += 3;
        return ((data[caret - 3] & 0xff) << 16) + ((data[caret - 2] & 0xff) << 8) + (data[caret - 1] & 0xff);
    }
 
    public int g4() {
        caret += 4;
        return ((data[caret - 4] & 0xff) << 24) + ((data[caret - 3] & 0xff) << 16) + ((data[caret - 2] & 0xff) << 8) + (data[caret - 1] & 0xff);
    }
 
    public String gstr() {
        int i = caret;
        while (data[caret++] != 0) ;
        return new String(data, i, caret - i - 1);
    }
    public byte data[];
    public int caret;
}

World.java:

 
/**
 *
 * @author Silabsoft
 */
public class World {
 
    private final int worldId;
    private final boolean members;
    private final HostCountry hostCountry;
    private final String host;
    private int players;
 
    World(int worldId, String host, boolean members, HostCountry hostCountry, int numberOfPlayers) {
        this.worldId = worldId;
        this.host = host;
        this.members = members;
        this.hostCountry = hostCountry;
        this.players = numberOfPlayers;
    }
 
    public String getHost() {
        return host;
    }
 
    public HostCountry getHostCountry() {
        return hostCountry;
    }
 
    public boolean isMembers() {
        return members;
    }
 
    public int getPlayers() {
        return players;
    }
 
    public int getWorldId() {
        return worldId;
    }
 
    public void setPlayers(int players) {
        this.players = players;
    }
 
    @Override
    public String toString() {
        return "World{" + "worldId=" + worldId + ", members=" + members + ", hostCountry=" + hostCountry + ", host=" + host + ", players=" + players + '}';
    }
}

WorldList.java:

 
/**
 *
 * @author Silabsoft
 */
import java.io.DataInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
 
public class WorldList {
 
    private final HashMap<Integer, World> worlds;
    private int worldCount;
    private final String worldListAddress;
    private int numberOfPlayers;
 
    public WorldList(String worldListAddress) {
        this.worldListAddress = worldListAddress;
        this.worlds = new HashMap<Integer, World>();
    }
 
    public void updateWorldList() throws IOException {
        numberOfPlayers = 0;
        HttpURLConnection url = (HttpURLConnection) new URL(worldListAddress).openConnection();
        DataInputStream in = new DataInputStream(url.getInputStream());
        byte data[] = new byte[url.getContentLength()];
        in.readFully(data);
        ByteStream p = new ByteStream(data);
        p.caret = 4; //skip first 4, might be a session id or timestamp
        int count = p.g2(); //   aq = dl1.ag(0x804d807d) * 0x54db551e;
 
 
        for (int i = 0; i < count; i++) {
            int j1 = p.g2();  // int j1 = dl1.ag(0x83d47af5);
            int worldId = (j1 & 0x7fff); // n1.c = 0xbe183a66 * (j1 & 0x7fff);
            boolean isMembers = j1 != 0;// n1.e = 0 != (j1 & 0xc5af3c81);
            String host = p.gstr(); // n1.f = dl1.ai(0x3bd62f26);
            int countryId = p.g1();// n1.y = dl1.az(0xdb8be48a) * 0x5932670f;
            int numberOfPlayers = p.g2b(); // n1.j = dl1.am((byte)-30) * 0xa5d501b;
            // n1.x = i1 * 0x53f5e1ef; 
            World w = new World(worldId, host, isMembers, HostCountry.getHostCountry(countryId), numberOfPlayers);
            this.worlds.put(worldId, w);
            this.numberOfPlayers += numberOfPlayers;
 
        }
    }
 
    public int getNumberOfPlayers() {
        return numberOfPlayers;
    }
 
    public int getWorldCount() {
        return worldCount;
    }
 
    public String getWorldListAddress() {
        return worldListAddress;
    }
 
    public HashMap<Integer, World> getWorlds() {
        return worlds;
    }
}

Test Run:

 
/**
 *
 * @author Silabsoft
 */
public class Main {
 
    public static void main(String[] args) throws Exception {
 
        WorldList l = new WorldList("http://www.runescape.com/slr.ws?order=LPWM");
        l.updateWorldList();
        System.out.println("total number of players: " + l.getNumberOfPlayers());
        l.updateWorldList();
        System.out.println("total number of players: " + l.getNumberOfPlayers());
 
        System.out.println(l.getWorlds().get(318));
    }
}

Java Runescape Bestiary Viewer

March 1st, 2013 by Silabsoft

Runescape recently released a new Bestiary displaying part of the all new Runetek 7 engine, Although It’s fun to look at it currently only supports google chrome. (inb4 google fanboys comment after my next statement) Myself I really don’t like using chrome and can’t really see myself just using 1 browser to view a bestiary for a game I don’t play. Due to the technical limitations of my firefox not being support by the bestiary I decided I would write a viewer in Java. Currently it only grabs the npc details but I hope to have it also be able to view the models and animations in the future. Google GSON made easy work of the json parsing and everything else is just standard swing using netbeans form builder.

rsbv 1024x619 Java Runescape Bestiary Viewer

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.silabsoft.runescape.bestiary;
 
import com.google.gson.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.silabsoft.runescape.bestiary.model.BestiaryName;
 
/**
 *
 * @author Silabsoft
 */
public class RunescapeBestiary extends javax.swing.JFrame {
 
    public static final String TITLE = "Silabsoft's Runescape Bestiary Viewer";
    private final DefaultMutableTreeNode bestiaryRootNode;
    public static final String alphabet[] = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
 
    /**
     * Creates new form RunescapeBestiary
     */
    public RunescapeBestiary() {
        bestiaryRootNode = new DefaultMutableTreeNode("Bestiary List");
 
        for (String s : alphabet) {
            bestiaryRootNode.add(new DefaultMutableTreeNode(s));
        }
        initComponents();
 
    }
 
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    //                          
    private void initComponents() {
 
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jProgressBar1 = new javax.swing.JProgressBar();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        updateMenuItem = new javax.swing.JMenuItem();
 
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(TITLE);
 
        jTree1.setModel(new javax.swing.tree.DefaultTreeModel(bestiaryRootNode));
        jScrollPane1.setViewportView(jTree1);
 
        jMenu1.setText("File");
 
        updateMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U, java.awt.event.InputEvent.CTRL_MASK));
        updateMenuItem.setText("Update");
        updateMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                updateMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(updateMenuItem);
 
        jMenuBar1.add(jMenu1);
 
        setJMenuBar(jMenuBar1);
 
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 529, Short.MAX_VALUE)
            .addComponent(jScrollPane1)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
 
        pack();
    }//                        
    int index = 0;
    private void updateMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                               
        UpdateTask updateTask = new UpdateTask();
        updateTask.addPropertyChangeListener(
                new PropertyChangeListener() {
 
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equals(evt.getPropertyName())) {
                            jProgressBar1.setValue((Integer) evt.getNewValue());
                        }
                    }
                });
        updateTask.execute();
    }                                              
 
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //
 
        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {
 
            public void run() {
                new RunescapeBestiary().setVisible(true);
            }
        });
    }
 
    private static String readUrl(String urlString) throws Exception {
        BufferedReader reader = null;
        try {
            URL url = new URL(urlString);
            reader = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuilder buffer = new StringBuilder();
            int read;
            char[] chars = new char[1024];
            while ((read = reader.read(chars)) != -1) {
                buffer.append(chars, 0, read);
            }
 
            return buffer.toString();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }
    // Variables declaration - do not modify                     
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTree jTree1;
    private javax.swing.JMenuItem updateMenuItem;
    // End of variables declaration                   
 
    class UpdateTask extends SwingWorker&lt;Integer, Object&gt; {
 
        int count;
 
        @Override
        public Integer doInBackground() {
            updateMenuItem.setEnabled(false);
            setTitle(TITLE + " UPDATING LIST");
            for (int i = 0; i &lt; 26; i++) {
 
                updateNode((DefaultMutableTreeNode) ((DefaultTreeModel) jTree1.getModel()).getChild(bestiaryRootNode, i), i);
                this.setProgress(100 * i / 25);
            }
 
            setTitle(TITLE + " UPDATING Bestiary Data");
            for (int i = 0; i &lt; 26; i++) {
                updateBeastData((DefaultMutableTreeNode) ((DefaultTreeModel) jTree1.getModel()).getChild(bestiaryRootNode, i));
                this.setProgress(100 * i / 25);
            }
            return count;
        }
 
        @Override
        protected void done() {
 
            try {
                setTitle(TITLE + " Mob Count: " + get());
            } catch (InterruptedException ex) {
            } catch (ExecutionException ex) {
            }
            updateMenuItem.setEnabled(true);
        }
 
        private void updateNode(DefaultMutableTreeNode child, int index) {
            Gson gson = new Gson();
            JsonParser jp = new JsonParser();
 
            JsonArray ja = null;
            try {
                ja = jp.parse(readUrl("http://services.runescape.com/m=itemdb_rs/bestiary/bestiaryNames.json?letter=" + alphabet[index])).getAsJsonArray();
            } catch (Exception ex) {
 
                return;
            }
            int size = ja.size();
            int idx = 0;
            for (int i = 0; i &lt; size; i++) {
                JsonObject jo = ja.get(i).getAsJsonObject();
 
                if (jo.has("npcs")) {
                    JsonArray npcArray = jo.getAsJsonArray("npcs");
                    DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(jo.get("dupe").getAsString());
                    ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(groupNode, child, idx++);
                    for (int x = 0; x &lt; npcArray.size(); x++) {
                        BestiaryName bn = gson.fromJson(npcArray.get(x), BestiaryName.class);
                        ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(bn), groupNode, x);
                        count++;
                    }
                } else {
 
                    BestiaryName bn = gson.fromJson(jo, BestiaryName.class);
 
                    ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(bn), child, idx++);
 
                    count++;
                }
 
            }
 
        }
 
        private void updateBeastData(DefaultMutableTreeNode child) {
            int size = child.getChildCount();
            for (int i = 0; i &lt; size; i++) {                 Object o = child.getChildAt(i);                 if (((DefaultMutableTreeNode) o).getChildCount() &gt; 0) {
                    updateBeastData((DefaultMutableTreeNode) o);
                } else {
 
                    parseBeastData((DefaultMutableTreeNode) o);
                }
            }
        }
 
        private void parseBeastData(DefaultMutableTreeNode node) {
            JsonParser jp = new JsonParser();
 
            JsonObject jo = null;
            try {
                jo = jp.parse(readUrl("http://services.runescape.com/m=itemdb_rs/bestiary/beastData.json?beastid=" + ((BestiaryName) node.getUserObject()).getValue())).getAsJsonObject();
 
            } catch (Exception ex) {
 
                return;
            }
            int idx = 0;
            for (Entry&lt;String, JsonElement&gt; e : jo.entrySet()) {
                insertBeastDataNode(node, e.getKey(), e.getValue());
 
            }
        }
 
        private void insertBeastDataNode(DefaultMutableTreeNode parent, String key, JsonElement value) {
            if (value.isJsonObject()) {
                DefaultMutableTreeNode dataCat = new DefaultMutableTreeNode(key);
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(dataCat, parent, parent.getChildCount());
                for (Entry&lt;String, JsonElement&gt; e : value.getAsJsonObject().entrySet()) {
 
                    insertBeastDataNode(dataCat, e.getKey(), e.getValue());
                }
            }
            else if(value.isJsonArray()){
                DefaultMutableTreeNode dataCat = new DefaultMutableTreeNode(key);
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(dataCat, parent, parent.getChildCount());
                JsonArray a = value.getAsJsonArray();
                int size = a.size();
                for(int i = 0; i &lt; size; i++){
 
                     ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(a.get(i)), dataCat,i);
                }
            }
            else {
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(key + ":" + value), parent, parent.getChildCount());
            }
        }
    }
}
package org.silabsoft.runescape.bestiary;
 
import com.google.gson.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Map.Entry;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import org.silabsoft.runescape.bestiary.model.BestiaryName;
 
/**
 *
 * @author Silabsoft
 */
public class RunescapeBestiary extends javax.swing.JFrame {
 
    public static final String TITLE = "Silabsoft's Runescape Bestiary Viewer";
    private final DefaultMutableTreeNode bestiaryRootNode;
    public static final String alphabet[] = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
 
    /**
     * Creates new form RunescapeBestiary
     */
    public RunescapeBestiary() {
        bestiaryRootNode = new DefaultMutableTreeNode("Bestiary List");
 
        for (String s : alphabet) {
            bestiaryRootNode.add(new DefaultMutableTreeNode(s));
        }
        initComponents();
 
    }
 
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    //                           
    private void initComponents() {
 
        jScrollPane1 = new javax.swing.JScrollPane();
        jTree1 = new javax.swing.JTree();
        jProgressBar1 = new javax.swing.JProgressBar();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        updateMenuItem = new javax.swing.JMenuItem();
 
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle(TITLE);
 
        jTree1.setModel(new javax.swing.tree.DefaultTreeModel(bestiaryRootNode));
        jScrollPane1.setViewportView(jTree1);
 
        jMenu1.setText("File");
 
        updateMenuItem.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_U, java.awt.event.InputEvent.CTRL_MASK));
        updateMenuItem.setText("Update");
        updateMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                updateMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(updateMenuItem);
 
        jMenuBar1.add(jMenu1);
 
        setJMenuBar(jMenuBar1);
 
        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, 529, Short.MAX_VALUE)
            .addComponent(jScrollPane1)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 254, Short.MAX_VALUE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
        );
 
        pack();
    }//                         
    int index = 0;
    private void updateMenuItemActionPerformed(java.awt.event.ActionEvent evt) {                                               
        UpdateTask updateTask = new UpdateTask();
        updateTask.addPropertyChangeListener(
                new PropertyChangeListener() {
 
                    public void propertyChange(PropertyChangeEvent evt) {
                        if ("progress".equals(evt.getPropertyName())) {
                            jProgressBar1.setValue((Integer) evt.getNewValue());
                        }
                    }
                });
        updateTask.execute();
    }                                              
 
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /*
         * Set the Nimbus look and feel
         */
        //
        /*
         * If Nimbus (introduced in Java SE 6) is not available, stay with the
         * default look and feel. For details see
         * http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(RunescapeBestiary.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //
 
        /*
         * Create and display the form
         */
        java.awt.EventQueue.invokeLater(new Runnable() {
 
            public void run() {
                new RunescapeBestiary().setVisible(true);
            }
        });
    }
 
    private static String readUrl(String urlString) throws Exception {
        BufferedReader reader = null;
        try {
            URL url = new URL(urlString);
            reader = new BufferedReader(new InputStreamReader(url.openStream()));
            StringBuilder buffer = new StringBuilder();
            int read;
            char[] chars = new char[1024];
            while ((read = reader.read(chars)) != -1) {
                buffer.append(chars, 0, read);
            }
 
            return buffer.toString();
        } finally {
            if (reader != null) {
                reader.close();
            }
        }
    }
    // Variables declaration - do not modify                     
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JProgressBar jProgressBar1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTree jTree1;
    private javax.swing.JMenuItem updateMenuItem;
    // End of variables declaration                   
 
    class UpdateTask extends SwingWorker&lt;Integer, Object&gt; {
 
        int count;
 
        @Override
        public Integer doInBackground() {
            updateMenuItem.setEnabled(false);
            setTitle(TITLE + " UPDATING LIST");
            for (int i = 0; i &lt; 26; i++) {
 
                updateNode((DefaultMutableTreeNode) ((DefaultTreeModel) jTree1.getModel()).getChild(bestiaryRootNode, i), i);
                this.setProgress(100 * i / 25);
            }
 
            setTitle(TITLE + " UPDATING Bestiary Data");
            for (int i = 0; i &lt; 26; i++) {
                updateBeastData((DefaultMutableTreeNode) ((DefaultTreeModel) jTree1.getModel()).getChild(bestiaryRootNode, i));
                this.setProgress(100 * i / 25);
            }
            return count;
        }
 
        @Override
        protected void done() {
 
            try {
                setTitle(TITLE + " Mob Count: " + get());
            } catch (InterruptedException ex) {
            } catch (ExecutionException ex) {
            }
            updateMenuItem.setEnabled(true);
        }
 
        private void updateNode(DefaultMutableTreeNode child, int index) {
            Gson gson = new Gson();
            JsonParser jp = new JsonParser();
 
            JsonArray ja = null;
            try {
                ja = jp.parse(readUrl("http://services.runescape.com/m=itemdb_rs/bestiary/bestiaryNames.json?letter=" + alphabet[index])).getAsJsonArray();
            } catch (Exception ex) {
 
                return;
            }
            int size = ja.size();
            int idx = 0;
            for (int i = 0; i &lt; size; i++) {
                JsonObject jo = ja.get(i).getAsJsonObject();
 
                if (jo.has("npcs")) {
                    JsonArray npcArray = jo.getAsJsonArray("npcs");
                    DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(jo.get("dupe").getAsString());
                    ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(groupNode, child, idx++);
                    for (int x = 0; x &lt; npcArray.size(); x++) {
                        BestiaryName bn = gson.fromJson(npcArray.get(x), BestiaryName.class);
                        ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(bn), groupNode, x);
                        count++;
                    }
                } else {
 
                    BestiaryName bn = gson.fromJson(jo, BestiaryName.class);
 
                    ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(bn), child, idx++);
 
                    count++;
                }
 
            }
 
        }
 
        private void updateBeastData(DefaultMutableTreeNode child) {
            int size = child.getChildCount();
            for (int i = 0; i &lt; size; i++) {                 Object o = child.getChildAt(i);                 if (((DefaultMutableTreeNode) o).getChildCount() &gt; 0) {
                    updateBeastData((DefaultMutableTreeNode) o);
                } else {
 
                    parseBeastData((DefaultMutableTreeNode) o);
                }
            }
        }
 
        private void parseBeastData(DefaultMutableTreeNode node) {
            JsonParser jp = new JsonParser();
 
            JsonObject jo = null;
            try {
                jo = jp.parse(readUrl("http://services.runescape.com/m=itemdb_rs/bestiary/beastData.json?beastid=" + ((BestiaryName) node.getUserObject()).getValue())).getAsJsonObject();
 
            } catch (Exception ex) {
 
                return;
            }
            int idx = 0;
            for (Entry&lt;String, JsonElement&gt; e : jo.entrySet()) {
                insertBeastDataNode(node, e.getKey(), e.getValue());
 
            }
        }
 
        private void insertBeastDataNode(DefaultMutableTreeNode parent, String key, JsonElement value) {
            if (value.isJsonObject()) {
                DefaultMutableTreeNode dataCat = new DefaultMutableTreeNode(key);
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(dataCat, parent, parent.getChildCount());
                for (Entry&lt;String, JsonElement&gt; e : value.getAsJsonObject().entrySet()) {
 
                    insertBeastDataNode(dataCat, e.getKey(), e.getValue());
                }
            }
            else if(value.isJsonArray()){
                DefaultMutableTreeNode dataCat = new DefaultMutableTreeNode(key);
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(dataCat, parent, parent.getChildCount());
                JsonArray a = value.getAsJsonArray();
                int size = a.size();
                for(int i = 0; i &lt; size; i++){
 
                     ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(a.get(i)), dataCat,i);
                }
            }
            else {
                ((DefaultTreeModel) jTree1.getModel()).insertNodeInto(new DefaultMutableTreeNode(key + ":" + value), parent, parent.getChildCount());
            }
        }
    }
}

Oldschool Runescape Revision 3

February 25th, 2013 by Silabsoft

Revision 3 was released today known changes include

The change for herbs from “unidentified” to “grimy” was reverted, by popular request.
Trade/Challenge offers will work more reliably for players with spaces in their names.
Behind-the-scenes preparatory work for a downloadable client was completed (see Accessing Old School RuneScape on the Client).

Download: revision_003

98rock log disabled

February 19th, 2013 by Silabsoft

Due to recent updates on the 98rock website I can no longer access the new log page without a proxy (U.S. copyright protection at its best) When I have time to view the new log page I will update my script. I will also release a download of the old database for anyone that is interested.

Shearing sheep without Shears

January 24th, 2013 by Silabsoft

So have you ever needed wool but forgot your shears? Maybe you simply needed to take 28 and didn’t want to drop them. Have no fear ProjectRS06 does not check if you have shears anyway

Feel Free to send the following packet:
ss Shearing sheep without Shears

and enjoy the results:

ss2 300x144 Shearing sheep without Shears

Recent Updates

January 15th, 2013 by Silabsoft

Tonight I finished a few updates so I though I would take a moment and post about them.

1) thanks to HcoJustin I have updated the WordPress RS Highscore widget. I hadn’t realized but three new activities had been added to Runescape since I initially wrote the plugin.

2) Although I use the forums mostly to entertain myself with spam bots I did switch to fluxBB for a future project I am currently working on. you can see it at http://silabsoft.org/forums

3) Added a page for the rs-web API it’s always been available but details on how to use have been vague I hope the 5 minutes of effort I put into writing the page will help some of you out there.

Character change exploit.

January 12th, 2013 by Silabsoft

You should never have open public commands on your server and if you do you should at least limit how many times they can be used. Here is a perfect example as to why. This client that I am releasing abuses rapidly sending 3 packets

The first packet it sends is ID: 103 – in the 317 client this is the command packet. I am sending the “::outfit command”

The second packet to be sent is the Character Design packet ID: 101

Finally the last packet to be sent is the button click packet ID: 85 YOu also need to know which button you have clicked for this example it happens to be button ID: 3651

The source of the CharacterChangeScape is included the jar the client jar is slightly modified to include some hooks of the stream class if you don’t trust it don’t use it.
Somepeople zps8bc04ad0 300x196 Character change exploit.
charChangeScape

HPAnnouncer for projectrs06

January 10th, 2013 by Silabsoft

HPAnnouncer

Just for those who wanted it.

jMonopoly – Java Monopoly game.

January 5th, 2013 by Silabsoft

So I was sitting in my house today and was thinking about how long its been since I last played Monopoly and started to get the itch to play. As I was searching online to find some Monopoly game to download I though about what a great idea it would be to write my own. So I have spent a few hours today and though I would share my progress. Also since silabsoft.org is my homepage I hoped this post would motivate me to continue working on it

jMonopoly jMonopoly    Java  Monopoly game.

The Dice Class:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.silabsoft.jmonopoly.model;
 
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.Comparator;
import java.util.Random;
 
/**
 *
 * @author Silabsoft
 */
public class Dice extends BoardEntity {
 
    private final BufferedImage[] diceImages;
    private final Random random = new Random();
    private int value;
    public static int t;
 
    public Dice(int x, int y, BufferedImage diceImages[]) {
        drawX = x;
        drawY = y;
        this.diceImages = diceImages;
 
        rollDice();
    }
 
    public Image getImage() {
        return diceImages[value - 1];
    }
 
    public void rollDice() {
        value = 1 + random.nextInt(6);
    }
 
    public int getValue() {
        return value;
    }
 
    public static boolean isDouble(Dice a, Dice b) {
        return a.getValue() == b.getValue();
    }
 
    public boolean isDouble(Dice compare) {
        return this.getValue() == compare.getValue();
    }
 
    public int getTotal(Dice dice) {
        return this.getValue() + dice.getValue();
    }
 
    public static int getTotal(Dice a, Dice b) {
        return a.getValue() + b.getValue();
    }
}