Jump to content

[GUIDE] Create your own custom Ragnarök Online Client for Windows, Linux and MacOS

Recommended Posts


The objective of this guide is to create a full client that can run on every platform and where you have complete control over the source code of it, meaning you can add new windows, style every part of the game and adapt it to suit your server need. To do so we'll rely on a stack made of node-js with electron framework and express combined with RoBrowser from KeyWorld.


Text Editor

Get a good text editor, my personal choice for this will be atom : https://atom.io/


Download RoBrowser from here : https://www.robrowser.com/

Follow the instructions present here to set it up : https://www.robrowser.com/getting-started

You'll need a webserver for the first setup, if you're on Linux use Apache with PHP other wise you can get a nice wamp stack here : http://www.easyphp.org/

This is the basic result you should at least get to before continuing this tutorial : 




Download NodeJS from here : https://nodejs.org/en/

Install it and restart your computer.

Open a terminal / Windows Command Line and type the following : 

npm install -g electron-forge

Creating a new project

In the terminal, go to your working folder :

cd c:\projects

For the sake of this tutorial, we'll call our project "sakexe".

Now you'll initialize your project :

electron-forge init sakexe

A new folder named after the project was created, we'll move into this folder :

cd sakexe

We'll now install express :

npm install express --save

Open your project with atom :



Now we'll edit index.html to the following (replace ROConfig contents with whatever your configuration is) :

<!DOCTYPE html>
		<title>SakExe : FullClient</title>
		<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
		<script type="text/javascript" src="./api.js"></script>
		<script type="text/javascript">
			function initialize() {
				var ROConfig = {
					target:        document.getElementById("robrowser"),
					type:          ROBrowser.TYPE.FRAME,
					application:   ROBrowser.APP.ONLINE,
					remoteClient:  "",
					development:    false,
					servers: [{
						display:     "Demo Server",
						desc:        "roBrowser's demo server",
						address:     "",
						port:        7000,
						version:     25,
						langtype:    12,
						packetver:   20131223,
						packetKeys:  true,
						socketProxy: "ws://",
						adminList:   [2000000]
					skipServerList:  true,
					skipIntro:       true,
				var RO = new ROBrowser(ROConfig);
			window.addEventListener("load", initialize, false);
			html, body, iframe, #robrowser {
				overflow: hidden;
				min-width: 800px;
				min-height: 600px;
		<div id="robrowser">Initializing roBrowser...</div>

Edit index.js to the following :

import { app, BrowserWindow } from 'electron';
const express = require('express');
const server = express();

// Handle server requests to serve static files
server.use('/', express.static((__dirname)));

// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;

const createWindow = () => {
  // Start listening to port 5737
  server.listen(5737, function() {});
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,

  // and load the index.html of the app.

  // Disabling the webtools
  mainWindow.webContents.on("devtools-opened", () => { mainWindow.webContents.closeDevTools(); });

  // Disabling the mainmenu

  // Emitted when the window is closed.
  mainWindow.on('closed', () => {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On OS X it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.

It's time to copy contents from your RoBrowser folder into your Sakexe folder so your file structure looks like this :



Now you can try your project by typing the following :

electron-forge start

Here's the expected result :




Your can now compile your project for your current platform by using :

electron-forge make

You can find more details about compilation and packaging at the following link : https://github.com/electron-userland/electron-forge


You can set an icon for your executable by following these instructions here : https://stackoverflow.com/questions/44122559/how-to-set-the-app-icon-using-electron-forge-package-on-mac


Thanks for reading 😘


2018-04-02 : Fixed a mistake in parameters sent to RoBrowser that'd try to load the client from RoBrowser repository instead of the local custom client. I plan to edit this guide later on to implement a websocket proxy directly into the electron framework to avoid having to set on up with RoBrowser.

Edited by SelfCastingCookies
  • Upvote 3
  • Love 1
  • MVP 6
Link to comment
Share on other sites

@Quesooo Thanks for the feedback, which source code do you need ? RoBrowser sources are available here : https://upload.robrowser.com/roBrowser.zip , the electron framework source code is generated by the command line : 

electron-forge init sakexe

and the sources I did modify are listed in "Code brackets".

Did I miss something ?

  • Upvote 1
Link to comment
Share on other sites

Updooted, nice guide.

Edit: Here's a mirror for roBrowser's source code.


SHA1: 2d8de69774442210cc7768c2aaf81cd49cbd5238
SHA256: c610180aac7f6ceb3e062d21ee951cd0db2bb1da2e2c4fee366b61f6432f1c25
MD5: 95ce6c6e9ec31e95838fca6746ecb5e1

Edited by Secrets
  • Upvote 2
Link to comment
Share on other sites

Love this idea, hoping to make this a reality for my test server and be able to share the nostalgia of RO with friends over Chrome

Link to comment
Share on other sites

I loved the idea and improved the concept in this repository (giving you credits):


The difference here is the use of env vars and separation from roBrowser base code. I will now convert roBrowser to a NPM package so we can use in this project as dependency instead of just copying it. Then I will convert the PHP remote client to NodeJS. This way we don't need a server with PHP support and we could just run the whole client locally (as Electron already runs the web server using Express).

  • MVP 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...

Important Information

By using this site, you agree to our Terms of Use and Privacy Policy.