Programming

Simple Oldschool Runescape worldlist grabber

Wednesday, March 6th, 2013

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

Friday, March 1st, 2013

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());
            }
        }
    }
}

98rock log disabled

Tuesday, February 19th, 2013

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

Thursday, January 24th, 2013

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

Character change exploit.

Saturday, January 12th, 2013

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

Thursday, January 10th, 2013

HPAnnouncer

Just for those who wanted it.

jMonopoly – Java Monopoly game.

Saturday, January 5th, 2013

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();
    }
}

ProjectRS06 – remove the profanity Filter

Friday, December 28th, 2012

Davidi is a lazy guy and left the profanity filter intact this small bytecode patch will fix the issue.

You will be looking for this:

 
invokestatic java/lang/System/currentTimeMillis()J
pop2
aload_0
invokevirtual java/lang/String/toCharArray()[C
astore_1
aload_1
invokestatic A/arraycopy([C)V
new java/lang/String
dup
aload_1
invokespecial java/lang/String/<init>([C)V
invokevirtual java/lang/String/trim()Ljava/lang/String;
astore_2
aload_2
invokevirtual java/lang/String/toLowerCase()Ljava/lang/String;
invokevirtual java/lang/String/toCharArray()[C
astore_1
aload_2
invokevirtual java/lang/String/toLowerCase()Ljava/lang/String;
astore_3
aload_1
invokestatic A/currentTimeMillis([C)V
aload_1
invokestatic A/toCharArray([C)V
aload_1
invokestatic A/toLowerCase([C)V
aload_1
invokestatic A/trim([C)V
getstatic A/trim [Ljava/lang/String;
dup
astore 7
arraylength
istore 6
iconst_0
istore 5
goto 65
aload 7
iload 5
aaload
astore 4
iconst_m1
istore 8
goto 54
aload 4
invokevirtual java/lang/String/toCharArray()[C
astore 9
aload 9
iconst_0
aload_1
iload 8
aload 9
arraylength
invokestatic java/lang/System/arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V
aload_3
aload 4
iload 8
iconst_1
iadd
invokevirtual java/lang/String/indexOf(Ljava/lang/String;I)I
dup
istore 8
iconst_m1
if_icmpne 44
iinc 5 1
iload 5
iload 6
if_icmplt 37
aload_2
invokevirtual java/lang/String/toCharArray()[C
aload_1
invokestatic A/currentTimeMillis([C[C)V
aload_1
invokestatic A/indexOf([C)V
invokestatic java/lang/System/currentTimeMillis()J
pop2
new java/lang/String
dup
aload_1
invokespecial java/lang/String/<init>([C)V
invokevirtual java/lang/String/trim()Ljava/lang/String;
areturn

now simply Change it to:

aload_0
invokevirtual java/lang/String/toCharArray()[C
astore_1
new java/lang/String
dup
aload_1
invokespecial java/lang/String/<init>([C)V
invokevirtual java/lang/String/trim()Ljava/lang/String;
areturn

Results:
profanity ProjectRS06   remove the profanity Filter

Don’t have the stomach for bytecode editing. it’s ok I provided a modified client ready for download

SilabClient_v2

My experiene with HitTail

Tuesday, December 18th, 2012

Recently I just finished a free trial with HitTail.

For those that don’t know what HitTail is:

HitTail tells you, in real-time, the most promising search terms you should target based on your existing traffic. We do this using a sophisticated algorithm tuned by analyzing over 1.2 billion keywords.

I used it on silabsoft.org just to see if it would be useful to purchase for other sites. Overall the tool seems pretty useful I did get at least one keyword that I was able to focus and snag the top position on Google for that keyword. It’s also priced reasonably for smaller websites However if you have a larger website you might find the price to be a bit steep. Installation was an absolute breeze especially for WordPress users as they have taken the time to write a simple plugin that makes the installation almost idiot proof. The sites back end is easy to understand and read and the suggestions are placed in a nice table for you to view. They even sent me an email everything they had a new keyword to suggest to me. They also include a service to write articles for each of your suggested keywords. I didn’t try this as the price is much higher than I can afford for this shitty little website but I would consider it for some of the other websites I run. Overall with Google Analytics and Webmaster Tools I think HitTail is a essential asset for a small website looking to increase organic search traffic.

For those of you interested in checking them out you can do so by going to http://HitTail.com

TabZazz simple tab delimited file manipulation.

Wednesday, December 12th, 2012

Recently I was going through the tedious task of data from an excel spreadsheet and pasting it into a formatted email, then taking the same data and adding it to a website. I had enough of it and decided that I would write a simple application that could take the contents of a Tab delimited spreadsheet and a template file and output as I desire. I named it TabZazz. I will probably take the time in the future to extends the features in the future a I know right now its very crude and basic but it got the job done easily enough.

/**
 *
 * @author Silabsoft
 */
public class TabZazz {
 
    private final String splitter;
    private String[][] data;
    private ArrayList<String> template;
 
    public TabZazz(String splitter) {
        this.splitter = splitter;
 
    }
 
    public TabZazz() {
        this("\t");
    }
 
    public void zazz(InputStream data, InputStream template, OutputStream out) throws IOException {
        parseData(data);
        parseTemplate(template);
        output(out);
    }
 
    public void parseData(InputStream data) throws IOException {
        BufferedReader d = new BufferedReader(new InputStreamReader(data));
 
        ArrayList<String[]> ph = new ArrayList<String[]>();
        String l = d.readLine();
        while (l != null) {
            String sd[] = l.split(splitter);
            ph.add(sd);
            l = d.readLine();
        }
        this.data = new String[ph.size()][];
        for (int i = 0; i < ph.size(); i++) {
            this.data[i] = ph.get(i);
        }
        d.close();
        ph.clear();
    }
 
    public void parseTemplate(InputStream data) throws IOException {
        BufferedReader d = new BufferedReader(new InputStreamReader(data));
        String l = d.readLine();
        this.template = new ArrayList<String>();
        while (l != null) {
            this.template.add(l);
 
            l = d.readLine();
 
        }
        d.close();
    }
 
    public void output(OutputStream out) {
        PrintStream ps = new PrintStream(out);
 
        for (int i = 1; i < data.length; i++) {
            int c = 0;
            for (String t : this.template) {
 
                while (t.contains("[?]")) {
                    t = t.replace("[?]", data[i][c++]);
                }
                ps.println(t);
            }
        }
        ps.close();
    }
}

Example Data:

SKU	Size (mm):	Rated Voltage (VDC):	Operating Voltage Range (VDC):	Current Amp (Amp):	Rate Input Power (Watt):	Speed (rpm):	Max Air Flow (CMF):	Max Static Prestture (Inch - H2O):	Noise Level (dB-A):	Weight (g):
DC20060A	200*200*60mm	2400	 14.0 to 27.6	1.6	38.4	2800	595	0.82	65	1031.4
DC20060B	200*200*60mm	2400	14.0 to 27.6	1.5	36	2500	532	0.75	58	1031.4

Example Template:

SKU: [?]
[!size:[?]!]
Rated Voltage: [?] (VDC)
Operating Voltage Range: [?] (VDC)
Current Amp: [?] (Amp)
Rate Input Power: [?] (Watt)
Speed: [?] (rpm)
Max Air Flow: [?] (CMF)
Max Static Prestture: [?] (Inch - H2O)
Noise Level: [?] (dB-A)
Weight: [?] (g)

Example Output:

SKU: DC20060A
 
[!size:200*200*60mm!]
Rated Voltage: 2400 (VDC)
Operating Voltage Range:  14.0 to 27.6 (VDC)
Current Amp: 1.6 (Amp)
Rate Input Power: 38.4 (Watt)
Speed: 2800 (rpm)
Max Air Flow: 595 (CMF)
Max Static Prestture: 0.82 (Inch - H2O)
Noise Level: 65 (dB-A)
Weight: 1031.4 (g)
 
 
 
 
==
SKU: DC20060B
 
[!size:200*200*60mm!]
Rated Voltage: 2400 (VDC)
Operating Voltage Range: 14.0 to 27.6 (VDC)
Current Amp: 1.5 (Amp)
Rate Input Power: 36 (Watt)
Speed: 2500 (rpm)
Max Air Flow: 532 (CMF)
Max Static Prestture: 0.75 (Inch - H2O)
Noise Level: 58 (dB-A)
Weight: 1031.4 (g)