What Can Be Modded and What Can't?; Modding Part 2

Client-Sided vs Server-Sided

If the game you are modding is solely single player, you can skip this part. If it is an online game or has even a bit of online aspect (like PvP), you might want to read on.

When I released the Grow Stone mod, many people asked me to mod this or mod that, but especially in an online game where the game communicates with the server, some things can't be modded since the data is stored on there server. These elements are called server-sided and can't be modded. What you can mod are the client-sided elements, where the calculations or data are stored on your device and not the server.

For example, people ask for an unlimited ruby (premium currency) mod. This was obviously impossible as the data about currency, ruby and gold, were stored on the server. How I knew this was because when I looked at how the client dealt with transactions, all it did was send packets with the item you wanted to buy.

Quick note: if you don't know what a packet is; it is basically like a virtual package containing information that is sent between your client and the server. This is how an app communicates with the server.

So, let's say I buy a mystery package with gaia items (let's just say 100 rubies), what the game does is: You press the buy button -> the client sends a packet containing the item ID to the server saying you want to buy this -> in the server, it gets the price of the item with the ID and subtracts it from your current ruby (remember, it's all on the server) if you have enough -> if you don't have enough, it sends a failed packet and if you had enough, it adds the items to your inventory data on the server and is then shown on the client.

How did I know this?? By reverse engineering the game and looking at its code! Like we did in part 1, I used a .NET dissembler like DnSpy to look through the classes and find which one deals with transactions and perhaps currency. 

In this article, I'll be covering how I decided that currency and auto combine time is server sided by reverse engineering the methods.

My Thought Process

Example One

Here's my thought process while reverse engineering this application to see how the transaction works.

After I load my Assembly-CSharp.dll file onto a dissembler (I'm using DnSpy and I suggest you do the same after you understand how editing IL code works), I look at the classes.

As you can see, it is super long, but I like to take the time to look through and match up what each class does for the whole game (like analyzing each puzzle piece). 

Let's say in this case, I want to see if I can add more rubies or gold for myself :p

I want to find anything that uses rubies or gold, I think the easiest should be to find the shop classes and work my way down from there. I can either search it or find the class myself. The problem with searching is that it might show too many things that it just gets messy and cumbersome.

Oh look, I found this class while I was just scrolling down and found a method called BuyCashItem:

That must be a transaction thing, using gold or ruby!

Looking at the method, I see that it is calling another method called BuyCashItem() from another class called MyGameManager.

MyGameManager.Get().BuyCashItem(blah blah parameters blah);

this line gets the instance of MyGameManager with Get() and calls the function inside of it called BuyCashItem. It is using Get() to grab an instance of the class since BuyCashItem isn't a static function. What is a static function?

So we click that to see what it is.


Right away, I notice this WorldClient.Get().SendPacket(blah)


So, my game client is sending the server a packet after recording some stuff (the if(recordForFixError ) part). What is it sending?

So from looking at this, SendPacket() method has two parameters: the packet type, and an object corresponding to the packet type.

The Packet.Type.BuyCashItem is just a number which the server uses to see what item I clicked buy on.

The "new BuyCashItem{}" part is creating an object of the class BuyCashItem with the data inside the {} brackets.

So the object has 5 attributes: itemID, priceType, signedData, signature, and receiverID.

I'm guessing the itemID is the ID that identifies what item it is, price type is what currency is uses, and the rest sounds like just verification or whatever, I don't care.

The delegate(Packet P) is the callback function, when the packet is returned from the server after it processes what you sent. We'll go over this soon.

So as you can see, the transaction is handled by packet sending and all the math and data is process on the server. All your client sends is "Hey I want to buy XXX item" and the server checks if you can buy that and updates your inventory or bank according to your situation.

You can repeat the process a few more times, looking for other code that deals with currency, and in my case, all the transactions were handled on the server in the same manner, so it was obvious that currency data was stored online.

I hope that helped you understand how to determine whether you can mod certain features of the game.


Example Two


If not, let's do another example. I want to see if I can modify the timer on the auto combination buff to make it auto combine faster! (Grow Stone Online reference).

Okay so I need to find out what part of the code deals with auto combine.

I looked over the classes and didn't see anything promising that will lead me to auto combine so I'm going to search it. Ctrl+Shift+K "autocombine" Well, got nothing.

Okay this is going to take some time to find. This actually took me a bit of time so don't get frustrated early if finding a certain thing takes a bit of time.

I look over all the classes for possible clues: I found a class called Drag Object, which I thought would be useful since you have to drag objects to create a new stone. Maybe this has something to do with autocombine?

To backtrace from here and find out what we want, we will analyze this class (right click ->Analyze)


On the bottom right panel, you see the Analyzer section and when you open it, you can see which methods use the Drag Object class!

Okay, so I see a Panel_Items_Bag.OnDropItem(). This caught my attention because I can infer that Panel_Items_Bag is the class that takes care of my item bag, which is where the stone is combined.

Great, so I double click that to follow that.


Okay, so skimming it, I can see how combining stones work (When you drag a stone onto another) and the process behind it. This will come useful when we create our own AutoCombine! Which we will go over on the next part. 

Well, the method didn't end up containing anything about auto combining.

So let's look at the Panel_Items_Bag class.

I'm looking around and I come across a function called HandleEvent, which by glance looks like a class that handles packets sent by servers.














It has a bunch of if statements checking if the packet types match up and BOOM, we got a packet type called ItemAutoComposed. 

That's definitely it. 


Okay, so when the server sends a packet with type = ItemAutoComposed, it gets the ItemAutoComposed object that's inside the packet. The Object contains which stone was combined with which (this was calculated on the server) and then calls DOCompose() with the data (which is probably just a method that animates the two items, you can check just by simply following that method). The item made was already craft on the server and processed into your on-server data. What you would see is just the animation and an update on your game bag with new data from the server.

Okay so now we know that autocombine works when the server sends a packet to do auto combine. Then the timer must be on the server, so we declare this server-sided!

Comments

  1. Hey thanks that you spent time creating this and other post , i dont dont anyone else like you and your post is extremely helpful , i will try later for some game and it hope it work for all android game

    ReplyDelete

Post a Comment

Popular Posts