Actions

Game Protocol recap

From RuneWiki

Revision as of 15:20, 4 July 2024 by Pazaz (talk | contribs)

I'm going to recap everything we know about the game server's protocol so beginners and veterans can refine their understanding a bit. We're going to be using some terms that will conflict with the last 20 years of RSPS, keep an open mind!

We'll cover the basics first and touch on more in-depth details after.

Basics

Data Sizes

A byte is the smallest unit of data you can store in memory. You can edit the bits that make up a byte, but you're always working with bytes.

Signed numbers means they can have a minus sign. They can represent values from -<data range> to <data range>.

Unsigned numbers means they cannot have a minus sign. They can represent values from 0 to <data range>.

Java int types are signed and may represent values between -2,147,483,648 to 2,147,483,647 (-2.147b to 2.147b).

Java byte types are signed and may represent values between -128 and 127.

Numbers can be converted between signed/unsigned at any time if you store the result in the right data types.

TCP

TCP is a stream protocol, you can expect to send a byte on one end and the other end will receive that byte in the exact same order (simplification).

Opcodes

Opcodes means "Operation Codes" which is another way to say, if this byte is received then do this. The first byte(s) of a packet are the opcode. Note that I say byte(s), that distinction is for RS after 2010, we'll revisit the reason later.

Isaac

Isaac is the stream cipher that Jagex uses to encrypt the opcode. Every byte that it processes changes the state permanently and both client/server must be doing the same operations in the same order at all times. Isaac is the stream cipher that Jagex uses to encrypt the opcode. Every byte that it processes changes the state permanently and both client/server must be doing the same operations in the same order at all times.

Isaac is the stream cipher that Jagex uses to encrypt the opcode. Every byte that it processes changes the state permanently and both client/server must be doing the same operations in the same order at all times.

When the client connects, it initializes Isaac with the exact same starting state as the server.

Packet Lengths

Packet lengths for these opcodes can be fixed or variable, lengths are important for two reasons: TCP is a byte stream protocol and you need to know how much to read off the socket, and Isaac must be deciphering/decrypting the same opcodes, in the same order, on both sides.

A fixed packet length is calculated by adding up all of the bytes that are sent and storing that result ahead of time.

A variable packet length is calculated when packets are written, the byte(s) following the opcode in this case are saying how many bytes the rest of the packet is.

Packet Writing/Reading Methods

The client has a class officially called Packet. Yes, even when it's used to read the cache it's still reading as Packet. People often call this Buffer, InputStream/OutputStream, or ByteStream.

Later revisions there's another class called PacketBit, some people have called this Packet. It contains the methods to read/write bits.


When the client is being obfuscated for release, the network protocol gets randomized in a couple ways...

Opcodes are scrambled - changed randomly each revision and for each platform

Reading/writing methods in the packet handlers may be replaced with their alt variants

Packet handlers are shuffled around to be in random locations, you cannot simply diff them in the same order after decompiling

Read along here: Packet.java

Writing
Jagex Name RSPS Name Description
p1 writeByte
p2 writeWord, writeShort
p3 writeMedium
p4 writeInt
p5
p6
p8 writeLong
pjstr writeString
pjstr2
pdata writeBytes
psmart
psmarts
pSmart2or4
pBit
Writing Alt (Obfuscation)
Jagex Name RSPS Name Description
p1_alt1
p1_alt2
p1_alt3
Reading
Jagex Name RSPS Name Description
g1
g2
g3
g4
g5
g6
g8
gjstr
gjstr2
gdata
gsmart
gsmarts
gBit
Reading Alt (Obfuscation)
Jagex Name RSPS Name Description
g1_alt1

Server Logic

The server has some unique behaviors when processing packets. RSProt has some info covering packet limits that the server receives but I'll go over that here as well.

Client packets are separated into two types - client events (tracking/handled internally by the client) and user events (actionable inputs).

When the server reaches the limit of 10 user events or 50 client events, packet decoding stops for that player this tick and continues again next tick. These limits may vary depending on your revision if you care about that level of detail, OSRS made a change at one point to increase it to 10 user events from 5.

Server packets are also separated into two types - high priority, and low priority. That's two packet queues you write into, this helps improve game responsiveness because the client will only process 5-100 packets every 20ms. The important packets process first (map/info packets/variables) and the lower-priority content packets appear after.

Priority Name
High VARP_SMALL / VARP_LARGE
High PLAYER_INFO
Low IF_SETTEXT

Deobfuscating Clients

I'm going to take you through what it looks like when you're looking at a correctly named client vs unrefactored client:

if (this.packetType == 176) {
   this.daysSinceRecoveriesChanged = this.in.g1_alt2();
   this.unreadMessages = this.in.g2_alt2();
   this.warnMembersInNonMembers = this.in.g1();
   this.lastAddress = this.in.g4_alt3();
   this.daysSinceLastLogin = this.in.g2();
   // ...
   this.packetType = -1;
   return true;
}
if(pktType == 176) {
   daysSinceRecovChange = inStream.method427();
   unreadMessages = inStream.method435();
   membersInt = inStream.readUnsignedByte();
   anInt1193 = inStream.method440();
   daysSinceLastLogin = inStream.readUnsignedWord();
   // ...
   pktType = -1;
   return true;
}

With the right Jagex naming, you can calculate the packet length by just adding 1 (g1) + 2 (g2) + 1 (g1) + 4 (g4) + 2 (g2) and know which methods to use on the "other side" immediately.

Sources

Lost City - 2004Scape (2024)

Blurite - RSProt (2024)

NXT beta client messages (2016)

NXT beta server messages (2016)

NXT beta C++ function names (2016)

Password Applet decompiled (2009)