Want to learn to make hacked clients? Want to contribute to our lovely community instead of just leeching. It'll take just a while to learn the basics, just start by following this guide!
Chapter 1 - Getting a fresh client
First you need to get the new version number. It'll be available over here:
www.realmofthemadgod.com/version.txt
Copy the version number and go to this link:
www.realmofthemadgod.com/AssembleeGameClient[version].swf
Replace the [version] with the series of numbers what you got from the version.txt.
For the current 19.1 client the link is:
http://www.realmofthemadgod.com/Asse...1389653812.swf
When the page has loaded press Ctrl + S to save the page to your computer.
Chapter 2 - Connecting to production
You'll notice that the client connects to testing. Don't panic, that is normal. We need to add the connect to production mod but first you need to decompile the frest client, but you also need a client for the earlier build where you'll be updating the _-names and line numbers from.
For this tutorial I'll use 19.0 Mod selector as the one where I'm updating the _-names and line numbers from. I'll update them to work with newest 19.1 client.
So now for the decompiling, it'll be easiest if you used batch scripts to help you. Open notepad and paste this code in:
Code:
swfdecompress.exe client191.swf
abcexport.exe client191.swf
rabcdasm.exe client191-1.abc
pause
Save it as Decompile.bat for example.
Do not forget to add the .bat extension. Place your RABCDAsm folder and rename the fresh client that you downloaded from the official website to client191.swf. Then run Decompile.bat.
Next edit the Decompile.bat to look like this, for example:
Code:
swfdecompress.exe client190.swf
abcexport.exe client190.swf
rabcdasm.exe client190-1.abc
pause
And get the 19.0 client from
here. Next place it in your RABCDAsm folder and rename it to client190.swf and run the batch script again.
It's good to give the clients a name that has their version number in it.
Open the following folder in the Mod selector you downloaded *\19.0_Mod_Selector\mods\19.0.0_prod and open 19.0.0_prod.xml with your preferred text editor. I'd recommend you to download
Notepad++, as it makes your life easier.
You'll see this:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<rotmg>
<mod id="Connect to Production Server">
<code file2mod="_-x5\_-1Wb.class.asasm"
line="498">
prod.txt
</code>
</mod>
</rotmg>
Now open the file that it says (*\client190\_-x5\_-1Wb.class.asasm). Now you need to find the same file from the new 19.1 client
but wait. You'll only see that there is no folder called _-x5 in the 19.1 client. Now you need a program called
AstroGrep. Download it if you haven't already and change the search path to point to the 19.1 client's folder (*\client191) and search from the already open _-1Wb.class.asasm file an unusual bit of code. I chose line number 601 and entered QName(PackageNamespace("flash.net"), "LocalConnection") in AstroGrep's search text field.
Notice that if AstroGrep gives you long list of results, you may want to choose something else than that part of code.
Press the search button and let it go through the files in *\client191 folder. It should find the following matches if you're using 19.1 client:
Code:
Memory.class.asasm
_-pk.class.asasm
_-Ek.class.asasm
_-1oC.class.asasm
Look at the right most colon on AstroGrep which says "Count". Now you should go back to Notepad++ where you have _-1Wb.class.asasm open. Press Ctrl + F and write there the part that you chose to look for. I wrote QName(PackageNamespace("flash.net"), "LocalConnection") on the search field as I chose that when we were deciding on an unusual part of code. Press count to see the number of matches in the document. It says that there is 3 matches for QName(PackageNamespace("flash.net"), "LocalConnection") in _-1Wb.class.asasm. That makes the number of possibilities smaller.
Notice the new file may not always have same amount of matches. Now we have only 2 potential matches for that file:
Code:
_-pk.class.asasm
_-1oC.class.asasm
Now that there is only few possibilities we can search if they match manually. Open both of those files in Notepad++. Start scrolling all the files at nearly same speeds. You'll see that _-pk has part that catches eye:
Code:
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_callbacks") type QName(PackageNamespace("", "#0"), "Object") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_mode") type QName(PackageNamespace("", "#0"), "uint") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-0Jq") type QName(PackageNamespace("flash.net"), "LocalConnection") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-Pq") type QName(PackageNamespace("flash.net"), "Socket") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-dr") type QName(PackageNamespace("flash.utils"), "ByteArray") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-0Go") type QName(PackageNamespace("", "#0"), "Object") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-0cE") type QName(PackageNamespace("flash.utils"), "Dictionary") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-oh") type QName(PackageNamespace("", "#0"), "String") value Utf8("") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-nB") type QName(PackageNamespace("", "#0"), "Boolean") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-rh") type QName(PackageNamespace("", "#0"), "String") end
trait slot QName(PrivateNamespace("*", "_-0o8:_-pk/instance#0"), "_-1c4") type QName(PackageNamespace("", "#0"), "String") end
If you scroll the _-1Wb.class.asasm down you'll notice that there is no such part in there.
In _-1oC.class.asasm this part catches my eye:
Code:
trait slot QName(PackageNamespace("", "#0"), "loaderInfo") flag METADATA type QName(PackageNamespace("flash.display"), "LoaderInfo")
metadata "Inject"
end ; metadata
end ; trait
trait slot QName(PackageNamespace("", "#0"), "_-0Dx") flag METADATA type QName(PackageNamespace("_-Pg"), "_-1Tf")
metadata "Inject"
end ; metadata
end ; trait
trait slot QName(PrivateNamespace("*", "_-Pg:_-1oC"), "_-A2") type QName(PackageNamespace("", "#0"), "Boolean") value False() end
trait slot QName(PrivateNamespace("*", "_-Pg:_-1oC"), "_-0Hv") type QName(PackageNamespace("_-0z8"), "_-LZ") end
trait method QName(PackageNamespace("", "#0"), "_-0lh")
Again if you scroll the _-1Wb.class.asasm to about same area you'll see quite much similar code:
Code:
trait slot QName(PackageNamespace("", "#0"), "loaderInfo") flag METADATA type QName(PackageNamespace("flash.display"), "LoaderInfo")
metadata "Inject"
end ; metadata
end ; trait
trait slot QName(PackageNamespace("", "#0"), "_-0o6") flag METADATA type QName(PackageNamespace("_-x5"), "_-OQ")
metadata "Inject"
end ; metadata
end ; trait
trait slot QName(PrivateNamespace("*", "_-x5:_-1Wb"), "_-mp") type QName(PackageNamespace("", "#0"), "Boolean") value False() end
trait slot QName(PrivateNamespace("*", "_-x5:_-1Wb"), "_-XM") type QName(PackageNamespace("_-1mW"), "_-1Y8") end
trait method QName(PackageNamespace("", "#0"), "_-5B")
The newer _-name for _-1Wb.class.asasm is _-1oC.class.asasm!
Now scroll to line number 498 in _-1Wb.class.asasm because the 19.0.0_prod.xml had that line marked down there. Then scroll in the _-1oC.class.asasm to about same lines of code and search for matches on surrounding code. You'll notice that line number 489 in _-1oC.class.asasm matches with the line number 498 in _-Wb.class.asasm. Check it for yourself they look really similar based on the surroundings.
The newer line number for 498 (_-1Wb.class.asasm) is 489 (_-1oC.class.asasm)!
Now you can edit the_-1oC.class.asasm by inserting a new row after line number 489 and copying the code from prod.txt which locates in same folder with 19.0.0_prod.xml. Insert the copied code on the new line you created (490).
Make sure to open prod.txt with Notepad++ to prevent errors caused by regular notepad.
Save the modification and go back to your RABCDAsm folder. Create a new batch script:
Code:
rabcasm.exe client191-1\client191-1.main.asasm
abcreplace.exe client191.swf 1 client191-1\client191-1.main.asasm
pause
Save it as Recompile.bat, for example, and run it. After it has completed recompiling the client191.swf test if your client connects to production.
Chapter 3 - Auto-Nexus
Open the mods folder on the mod selector and locate 19.0.0_autoNexus folder. Open 19.0.0_autoNexus.xml and you'll see this:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<rotmg>
<mod id="Auto-Nexus 20 Percent">
<code file2mod="com/company/assembleegameclient/objects/Player.class.asasm"
line="4982">
19.0.0_autoNexus_20.txt
</code>
</mod>
<mod id="Auto-Nexus 30 Percent">
<code file2mod="com/company/assembleegameclient/objects/Player.class.asasm"
line="4982">
19.0.0_autoNexus_30.txt
</code>
</mod>
<mod id="Auto-Nexus 40 Percent">
<code file2mod="com/company/assembleegameclient/objects/Player.class.asasm"
line="4982">
19.0.0_autoNexus_40.txt
</code>
</mod>
</rotmg>
There you'll see 3 different mods are added to the Mod selector list within this file. They're all auto-nexuses so no one uses them all at once. Pick just one of them, it doesn't really matter. Open the file where the mod needs to be added (*\client190\com\company\assembleegameclient\objec ts\Player.class.asasm). This time it will be the same file in the new 19.1 client, because the name of the file that needs to be modded is not a _-name. So this time you can also open the other file (*\client191\com\company\assembleegameclient\objec ts\Player.class.asasm) without any further searching.
Now in the 19.0 client's Player.class.asasm locate line number 4982 and pick some unusual part of code near line 4982. I picked this part of code from line 4978:
Code:
setproperty QName(PackageNamespace("", "#0"), "lastDamage_")
I searched how many matches are there for "lastDamage_" in 19.0 client's Player.class.asasm. Again I pressed Ctrl + F and put lastDamage_ in the search box and then pressed Count. There are 2 matches so I scrolled back to beginning of the file and searched for that again to see is it the first or second match that the place for auto-nexus code is near. This time it was the second match so I opened 19.1 client's Player.class.asasm and searched for the second match for lastDamage_ by pressing Ctrl + F and then pressing two times "Find next" button.
Now we can recognize that the code there looks nearly same as in the older Player.class.asasm so we are able to say that line number 4932 is the new line for auto-nexus code.
Next open file called 19.0.0_autoNexus_30.txt and you should see this:
Code:
; _-names
#set charHp "_-0Ie"
#set charMaxHp "_-0sG"
#set funcEscape "escape"
; code
pop
getlocal0
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "player_")
ifne END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Nexus"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Arena"
ifeq END
getlex QName(PackageNamespace(""), $"charHp")
getlex QName(PackageNamespace(""), $"charMaxHp")
convert_d
divide
pushdouble .3
ifgt END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "gs_")
getproperty QName(PackageNamespace(""), "gsc_")
callpropvoid QName(PackageNamespace(""), $"funcEscape"), 0
END:
pushtrue
The part we're interested in for now is this:
Code:
; _-names
#set charHp "_-0Ie"
#set charMaxHp "_-0sG"
#set funcEscape "escape"
Those are the _-names that the auto-nexus code refers to to make the function to work. Let's start seeking for the new _-names for these. Open up your AstroGrep and set the Search Path to point to the client190 folder. And let's first search for "_-0Ie". We're looking for a match that doesn't have _-name. For me GameObject.class.asasm seems like good match. Open GameObject.class.asasm from both, client190 and client191 folders.
Now search "_-0Ie" from the 19.0 client's GameObject.class.asasm. The first match looks bit hard to play with so I used the second match since there is more code around it to look for from the 19.1 client's GameObject.class.asasm:
Code:
trait slot QName(ProtectedNamespace("_-1cF"), "_-0B7") type QName(PackageNamespace("flash.display"), "BitmapData") value Null() end
trait slot QName(ProtectedNamespace("_-1cF"), "_-1g5") type QName(PackageNamespace("flash.utils"), "Dictionary") value Null() end
trait slot QName(PackageNamespace("", "#0"), "_-0sG") type QName(PackageNamespace("", "#0"), "int") value Integer(200) end
trait slot QName(PackageNamespace("", "#0"), "_-0Ie") type QName(PackageNamespace("", "#0"), "int") value Integer(200) end
trait slot QName(PackageNamespace("", "#0"), "size_") type QName(PackageNamespace("", "#0"), "int") value Integer(100) end
Let's choose something that we think helps us to find the new name in the 19.1 client's GameObject.class.asasm. I chose Integer(200) and searched in the 19.1 client's GameObject.class.asasm and found the same code block:
Code:
trait slot QName(ProtectedNamespace("_-Ko"), "_-0qU") type QName(PackageNamespace("flash.display"), "BitmapData") value Null() end
trait slot QName(ProtectedNamespace("_-Ko"), "_-NH") type QName(PackageNamespace("flash.utils"), "Dictionary") value Null() end
trait slot QName(PackageNamespace("", "#0"), "_-0J6") type QName(PackageNamespace("", "#0"), "int") value Integer(200) end
trait slot QName(PackageNamespace("", "#0"), "_-1nm") type QName(PackageNamespace("", "#0"), "int") value Integer(200) end
trait slot QName(PackageNamespace("", "#0"), "size_") type QName(PackageNamespace("", "#0"), "int") value Integer(100) end
_-1nm looks to have the same spot in the code as the old _-0Ie. That must be the new _-name! Now we have solved the first one of the names so replace the old one with the new one:
Code:
; _-names
#set charHp "_-1nm"
#set charMaxHp "_-0sG"
#set funcEscape "escape"
The second one of them is quite easy to solve using the same method so now try for yourself. Found it? Good, let's continue. Now it should look like this:
Code:
; _-names
#set charHp "_-1nm"
#set charMaxHp "_-0J6"
#set funcEscape "escape"
funcEscape almost never updates, so no need to worry about it for now. Now you're ready to place the code, but let's first make little modifications to the code:
Code:
; _-names
#set charHp "_-1nm"
#set charMaxHp "_-0J6"
#set funcEscape "escape"
; code
pop
getlocal0
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "player_")
ifne END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Nexus"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Arena"
ifeq END
;Here we have the safe areas so let's make a modification and add vault as a safe area because
;it is quite annoying if you connect to vault with low hp and it auto-nexuses you because of that
getlex QName(PackageNamespace(""), $"charHp")
getlex QName(PackageNamespace(""), $"charMaxHp")
convert_d
divide
pushdouble .3 ;This one changes the auto-nexus percentage so you can make for example a 25% auto-nexus, now let's try that
ifgt END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "gs_")
getproperty QName(PackageNamespace(""), "gsc_")
callpropvoid QName(PackageNamespace(""), $"funcEscape"), 0
END:
pushtrue
Now I've modified the code to look like this:
Code:
; _-names
#set charHp "_-1nm"
#set charMaxHp "_-0J6"
#set funcEscape "escape"
; code
pop
getlocal0
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "player_")
ifne END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Nexus"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Arena"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Vault" ; No more annoying nexusing from vault
ifeq END
getlex QName(PackageNamespace(""), $"charHp")
getlex QName(PackageNamespace(""), $"charMaxHp")
convert_d
divide
pushdouble .25 ; It's 25% now
ifgt END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "gs_")
getproperty QName(PackageNamespace(""), "gsc_")
callpropvoid QName(PackageNamespace(""), $"funcEscape"), 0
END:
pushtrue
As a side note I'll say now, if you want to have comment in the code, you can do that by using ; and writing your comment after that. Now we just need to add the code to the client. Make a new line after 4932 and insert the modified auto-nexus code there. It should look like this:
Code:
L589:
getlex QName(PackageNamespace("", "#0"), "_-1RH")
getlocal1
setproperty QName(PackageNamespace("", "#0"), "lastDamage_")
L592:
pushtrue
L593:
; _-names
#set charHp "_-1nm"
#set charMaxHp "_-0J6"
#set funcEscape "escape"
; code
pop
getlocal0
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "player_")
ifne END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Nexus"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Arena"
ifeq END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "name_")
pushstring "Vault" ; No more annoying nexusing from vault
ifeq END
getlex QName(PackageNamespace(""), $"charHp")
getlex QName(PackageNamespace(""), $"charMaxHp")
convert_d
divide
pushdouble .25 ; It's 25% now
ifgt END
getlex QName(PackageNamespace(""), "map_")
getproperty QName(PackageNamespace(""), "gs_")
getproperty QName(PackageNamespace(""), "gsc_")
callpropvoid QName(PackageNamespace(""), $"funcEscape"), 0
END:
pushtrue
returnvalue
end ; code
end ; body
end ; method
end ; trait
Now you're ready to recompile and test if it works.