Add data section + rewrite them

This commit is contained in:
PureCS 2018-07-03 05:59:44 -07:00
parent 769bdac9bf
commit 2f7502f346
12 changed files with 348 additions and 238 deletions

View File

@ -1,156 +1,217 @@
\[\[Category Cache\]\] # Archive format
== Introduction == From client revision 194 until 377, all the files in cache 0
are in an archive-like format which contains a collection of named
files (e.g. `BADENC.TXT` is a file which contains bad words in the
`wordenc` archive).
Since 194 all way up until 377, all the files in cache 0 have an ## Usage
archive-like format which contains a collection of named files (e.g.
'''BADENC.TXT''' is a file which contains bad words in the '''wordenc'''
archive).
=== Diagram === These files are used by the client for a variety of purpose.
------------------------------------------------------------------------ The files themselves represent either an index, which contains
information about to where to locate data in the cache, and
the data themselves.
\[http://img263.imageshack.us/img263/9678/68481568.png External Diagram e.g. `DATA` contains data for interfaces.
Image\]
== Usage == e.g. `MAP_INDEX` contains information about where to find the map and landscape files in the cache.
These files are used by the client for a variety of purposes. Some, such ## Format
as the '''DATA''' file contain data themselves (in this case the
interfaces). Others, such as the '''MAP\_INDEX''' file, contain
information about where to locate the map and landscape files in the
cache.
== Format == ```
tribyte uncompressedSize
tribyte uncompressedsize tribyte compressedsize tribyte compressedSize
```
If the uncompressed and compressed sizes are equal, the whole file is If the uncompressed and compressed sizes are equal, the whole file is
not compressed but the individual entries are compressed using bzip2. If not compressed but the individual entries are compressed using bzip2.
they are not equal, the entire file is compressed using bzip2 but the If they are not equal, the entire file is compressed using bzip2 but
individual entries are not. the individual entries are not.
Also note, the magic id at the start of the bzip2 entries are not Note: The magic id at the start of the bzip2 entries are not included
included in the cache. If you use an existing API to read the files and in the cache.
want to add this back, you must append the four characters: BZh1 before If you use an existing API to read the files and want to add this back,
you decompress. you must append the characters `BZh1` before you decompress.
short fileCount ```short fileCount```
Each file entry has the format: Each file entry has the format:
int nameHash tribyte uncompressedSize tribyte compressedSize ```
int nameHash
tribyte uncompressedSize
tribyte compressedSize
```
When you are looping through the files, you need to keep track of the # Extracting the data
file offset yourself. This psuedocode demonstrates how:
int offset = buffer.getCurrentOffset() + numFiles \* 10; for(int i = 0; If you iterate over the files using a for-loop, you need to keep track of the
i \< numFiles; i++) { // read values int thisFileOffset = offset; offset file offset.
+= thisFileCompressedSize; } The following pseudo-code demonstates how:
To get a named file by its name, you should first hash the name using ```java
this method: int offset = buffer.getCurrentOffset() + numFiles * 10;
public static int hash(String name) { int hash = 0; name = for(int i = 0; i < numFiles; i++) {
name.toUpperCase(); for(int j = 0; j \< name.length(); j++) { hash = // read values
(hash \* 61 + name.charAt(j)) - 32; } return hash; } int thisFileOffset = offset;
offset += thisFileCompressedSize;
}
```
To acquire a named file using its name, hash the name as follows:
```java
public static int hash(String name) {
int hash = 0;
name = name.toUpperCase();
for(int j = 0; j < name.length(); j++) {
hash = (hash * 61 + name.charAt(j)) - 32;
}
return hash;
}
```
Then, loop through the file entries you loaded earlier to find a Then, loop through the file entries you loaded earlier to find a
matching hash. Read the compressed file size from the offset. If the matching hash. Read the compressed file size from the offset. If the
whole file is not compressed, you should decompress the individual whole file is not compressed, you should decompress the individual
entry. entry.
== '''\#194 Archive Format''' == ## \#194 Archive Format
The 194 (RuneScape 2 beta) client worked with a very simple cache The \#194 (RuneScape 2 beta) client worked with a very simple cache
format. Each file in the cache was a file on the operating system. format.
Each file in the cache corresponded to a file on the operating system.
=== Name hashing === ### Name hashing
Every name in the cache was hashed using the following method which is, Every name in the cache was hashed using the following method which is,
incidentally, similar to the way player names are converted to longs. incidentally, similar to the way player names are converted to longs.
public static final long gethash(String string) { string = ```java
string.trim(); long l = 0L; for (int i = 0; i \< string.length() && i \< public static final long gethash(String string) {
12; i++) { char c = string.charAt(i); l \*= 37L; if (c \>= 'A' && c \<= string = string.trim();
'Z') l += (long) ('\\001' + c - 'A'); else if (c \>= 'a' && c \<= 'z') l long l = 0L;
+= (long) ('\\001' + c - 'a'); else if (c \>= '0' && c \<= '9') l +=
(long) ('\\033' + c - '0'); } return l; } for (int i = 0; i < string.length() && i < 12; i++) {
char c = string.charAt(i);
l \*= 37L;
if (c >= 'A' && c <= 'Z')
l += (long) ('\\001' + c - 'A');
else if (c >= 'a' && c <= 'z')
l += (long) ('\\001' + c - 'a');
else if (c >= '0' && c <= '9')
l += (long) ('\\033' + c - '0');
}
return l;
}
```
The resulting long was converted to a string and the file was given that The resulting long was converted to a string and the file was given that
name. name.
=== Files === ### Files
The files in the cache were the ones used in the \[\[JAGGRAB The files in the cache were the ones used in the [JAGGRAB protocol](./JAGGRAB-Protocol.html) (i.e. files in cache 0 in old engine caches),
Protocol\|JAGGRAB Protocol\]\] (i.e. files in cache 0 in old engine map (mX_Y), and landscape (lX_Y) files.
caches) and map (mX\_Y) and landscape (lX\_Y) files. Incidentally, this
naming is very similar to the names of the map and landscape files in
new engine caches.
== '''\#317 Archive Format''' == Incidentally, this naming is very similar to the names of the map and
landscape files in new engine caches.
## \#317 Archive Format
The old engine cache is made up two types of files. The old engine cache is made up two types of files.
=== Data file === ### Data file
The data file holds all of the files in the cache and is named The data file holds all of the files in the cache and is named
'''main\_file\_cache.dat'''. It is therefore very big, typically \~10-20 `main_file_cache.dat`.
megabytes.. It is therefore very big, typically ~10-20MB in size.
=== Index file === ### Index file
There are several index files, named '''main\_file\_cache.idx''' and There are several index files, named `main_file_cache.idx` and
then postfixed with a number. Each index file holds 'pointers' to where then post-fixed with a number.
a file is located in the main cache. Each index file represents a type Each index file holds 'pointers' to where a file is located in
of file. the main cache.
Each index file represents a type of file.
=== Index file format === ### Index file format
The index file is made up of 6 byte blocks which hold information about The index file is comprised of a collection of six byte blocks which hold
where a file can be located in the data file. The format of a single information about where a file can be located in the data file.
block is as follows:
tribyte fileSize tribyte initialDataBlockId The format of a single block is as follows:
```
tribyte fileSize
tribyte initialDataBlockId
```
=== Data file format === ### Data file format
The data file is made up of 520 byte blocks. The format of each of these The data file is comprised of a collection of 520 byte blocks.
blocks is as follows:
short nextFileId short currentFilePartId tribyte nextDataBlockId byte The format of each of these blocks is as follows:
nextFileTypeId byte\[512\] blockData
=== Explanation === ```
short nextFileId
short currentFilePartId
tribyte nextDataBlockId
byte nextFileTypeId
byte[512] blockData
```
An example will be used here as it is easier to follow. ### Running example
Let us say, the client wishes to fetch file type 2, file id 17. Suppose, the client wishes to fetch file type 2, file id 17.
First off, it will open the main\_file\_cache.idx2 file and seek to the First off, it will open the `main_file_cache.idx2` file and seek to the
index 17 \* 6 (102). It will then read two tribytes. index `17 * 6` (102).
It will then read the two tribytes:
```
fileSize = 1200
intialDataBlockId = 4
```
fileSize = 1200 intialDataBlockId = 4 The client will now open the `main_file_cache.dat` file and seek to the
index `4 * 520` (2080).
The client will now open the main\_file\_cache.dat file and seek to the It will then read the following:
index 4 \* 520 (2080). The values it reads will be: ```
nextFileId = 17
nextFileId = 17 currentFilePartId = 0 nextDataBlockId = 5 nextFileTypeId currentFilePartId = 0
= 2 blockData = ... nextDataBlockId = 5
nextFileTypeId = 2
blockData = ... // 512 bytes of data
```
It will read the first 512 bytes of the file and then knows that there It will read the first 512 bytes of the file and then knows that there
is 688 bytes left. Therefore, it has to read the next block. is 688 bytes left.
nextFileId = 17 currentFilePartId = 1 nextDataBlockId = 6 nextFileTypeId Therefore, it has to read the next block:
= 2 blockData ... ```
nextFileId = 17
currentFilePartId = 1
nextDataBlockId = 6
nextFileTypeId = 2
blockData ... // 512 bytes of data
```
It reads these next 512 bytes of the file and now knows that there are It reads these next 512 bytes of the file and now knows that there are
176 bytes left. So for a final time, it will read the next block. 176 bytes left.
nextFileId = 18 currentFilePartId = 2 nextDataBlockId = 7 nextFileTypeId So for a final time, it will read the next block:
= 2 blockData = ... ```
nextFileId = 18
currentFilePartId = 2
nextDataBlockId = 7
nextFileTypeId = 2
blockData = ... // 176 bytes of data
```
It can ignore most of these values (the next ones are meaningless at It can ignore most of these values (the next ones are meaningless at
this stage) and read the final 176 bytes. The whole 1200 byte file has this stage) and read the final 176 bytes.
now been read. The whole 1200 byte file has now been read.

View File

@ -1,3 +1,4 @@
A "DWord" (double-word) is a data-type that consists of 4 bytes.<br /> # DWord
A "DWord" (double-word) is a data-type that consists of 4 bytes.
It is also commonly known as the "int" data-type in programming. It is also commonly known as the "int" data-type in programming.
\[\[Category Data Type\]\]

View File

@ -1,85 +1,96 @@
== Introduction == # Data types
RuneScape uses a number of standard and non-standard data types. RuneScape uses a number of common and bespoke data types in the
process of data transmission.
== Byte Order == ## Byte Order
Data types that are two bytes or larger can be stored and ordered in a Data types that are two bytes or larger can be stored and ordered in a
variety of different ways. Generally people either use big endian or variety of different ways.
little endian. The traditional byte orders are big endian and little endian.
Generally people either use big endian or little endian.
=== Big Endian === RuneScape uses both little and big-endian byte orders throughout the
protocol (however, the 194 client only uses big-endian order).
This presumably to make reverse-engineering of the protocol harder.
Note: Some confusion has arisen over the byte order as the data types
are named incorrectly in Winterlove's server where little endian data
types are incorrectly named as big endian types.
### Big Endian
In big endian order, the most significant byte (MSB) is stored first and In big endian order, the most significant byte (MSB) is stored first and
the least significant byte (LSB) is stored last. the least significant byte (LSB) is stored last.
=== Little Endian === ### Little Endian
In little endian order, the least significant byte (LSB) is stored first In little endian order, the least significant byte (LSB) is stored first
and the most significant byte (MSB) is stored last. and the most significant byte (MSB) is stored last.
=== Byte order in RuneScape === ## Bespoke Byte Orders
RuneScape uses both little and big-endian byte orders throughout the
protocol (however, the 194 client only uses big-endian order),
presumably to make reverse-engineering of the protocol harder. Some
confusion has arisen over the byte order as the data types are named
incorrectly in \[\[Server Winterlove\|Winterlove\]\]'s server where
little endian data types are incorrectly named as big endian types.
== Standard data types == These datatypes can also be read/written by a
DataWriter/DataReader implementation (DataStreams and Buffers)
Naming conventions: {\| border=2 ! Official name ! Datatype name ! Jagex
name ! Encoding \|- \| Byte \| byte \| 1,1b \|- \| \[\[Word\|WORD\]\] \|
short \| 2,2b \|- \| \[\[DWord\|DWORD\]\] \| int,int32 \| 4,4b \|- \|
\[\[QWord\|QWORD\]\] \| long,int64 \| 8,8b \|- \| C style string \|
string,String,char *,char\[\] \| str,strbyte \| text bytes then '\n' or
10 \|- \| Java style string \| string,String,char *,char\[\] \| strraw
\| WORD length then text bytes \|}
Note that \[\[Jagex\]\] used to use a new line character as string
terminator, in more recent versions they use the null character \\0 or 0
to support multi-line strings.
== Non Standard Data Types ==
{\| border=2 ! Winterlove's name ! Jagex name ! Read transformation !
Write transformation \|- \| Special A \| Unknown \| value - 128 \| value
+ 128 \|- \| Special C \| Unknown \| 0 - value \| 0 - value \|- \|
Special S \| Unknown \| 128 - value \| 128 - value \|- \| SpaceSaverA \|
smarts \| (value\[0\] \< 128) ? (((value\[0\] - 128)\<\<8)+value\[1\]) :
value\[0\] \| if(value \< 128) putword(value+32768) else putbyte(value);
\|- \| SpaceSaverB \| smart \| (value\[0\] \< 128) ? value\[0\] - 64 \|
((value\[0\]\<\<8)+value\[1\]) - 49152 \| if(i \< 64 && i \>= -64)
putbyte(i + 64) else if(i \< 16384 && i \>= -16384) putword(i + 49152);
\|- \| tribyte / RGBColour / 3Byte / int3 / medium \| 3 \| (value\[0\]
\<\< 24) + (value\[1\] \<\< 16) + value\[2\] \| putbyte(value \>\>
24);putbyte(value \>\> 16);putbyte(value); \|- \| \[\[RS
String\|RS\_String\]\] \| jstr \| Old engine: read until newline
delimiter ("\n") <br />New engine: read until null byte (value 0). \|
Old engine: write and finish with newline delimiter ("\n") <br />New
engine: write and finish with null byte (value 0). \|}
Additionally, RuneScape also uses two endian orders for integers that Additionally, RuneScape also uses two endian orders for integers that
are different from a big- or low endian order. Both byte orders are are different from a big- or low endian order.
called middle-endian. We call these byte orders middle endian.
Their orders could be described as following: ### Middle Endian Big Int
Middle-endian big int: C3 D4 A1 B2 The bytes are stored in the following order, where A1 is the smallest byte (I.e. LSB) and D4 the bigger (i.e. MSB): C3 D4 A1 B2.
Middle-endian small int: B2 A1 D4 C3 ### Middle Endian Small Int
Where A1 is the smallest byte (LSB), and D4 the biggest byte (MSB). The bytes are stored in the following order, where A1 is the smallest byte (I.e. LSB) and D4 the bigger (i.e. MSB): B2 A1 D4 C3.
== Bit Access == ## Common data types
=== Initiating Bit Access === These data types are traditional, hence they can typically be written
and read by a standard DataStream, or Buffer implementation.
Naming conventions:
| Standardized name | Data-type name | Jagex name | Encoding |
|---|---|---|---|
| Byte | byte | 1,1b | Bytes |
| [Word](./Word.md) | short | 2,2b | Bytes |
| [DWord](./DWord.md) | int, int32 | 2,2b | Bytes |
| [QWord](./QWord.md) | long, int64 | 8,8b | Bytes |
| C-style String | string, String, char*, char[] | str, strbyte | Text bytes followed by `\n` or the byte `10`. |
| Java-string String | string, String, char*, char[] | strraw | Length as a word, followed by the text bytes. |
Note: In more recent versions of the client, C-style strings are terminated with the null character (i.e. `\0`) or the byte `0` to support multi-line strings.
## Bespoke data types
These data types are bespoke, that is, they were developed with the
sole intention of only being used within Jagex products.
We presume that this is another technique employed to make
reverse-engineering and packet manipulation harder.
Naming conventions:
| Winterlove's name | Jagex name | Read transformation | Write transformation |
|---|---|---|---|
| Special A | Unknown | value - 128 | value + 128 |
| Special C | Unknown | 0 - value | 0 - value |
| Special S | Unknown | 128 - value | 128 - value |
| SpaceSaverA | smarts | `(value[0] < 128) ? (((value[0] - 128) << 8) + value[1]) : value[0]` | `if(value < 128) putword(value+32768) else putbyte(value);` |
| SpaceSaverB | smart | `(value[0] << 24) + (value[1] << 16) + value[2] ` | `putbyte(value >> 24); putbyte(value >> 16); putbyte(value); ` |
| Tribyte, RGBColour, 3Byte, int3, medium | 3 | `(value[0] << 24) + (value[1] << 16) + value[2]` | `putbyte(value >> 24); putbyte(value >> 16); putbyte(value); ` |
| [RS String](./RS-String.md) | jstr | Old engine: read until newline terminated ("\n"). New engine: read until null byte (value 0). | Old engine: write and finish with newline delimiter ("\n"). New engine: write and finish with null byte (value 0). |
Note: The read transformation is the process which must be applied to
read data, to reconstruct the original.
The write transformation applies analogously, to when data is written.
## Bit Access
### Initiating Bit Access
Whenever data is to be sent to the server or to the client using bits; Whenever data is to be sent to the server or to the client using bits;
the stream needs to be prepared by setting the bit position. The bit the stream needs to be prepared by setting the bit position.
position can be calculated by multiplying the current buffer position by The bit position can be calculated by multiplying the current buffer
8. This is because each byte is comprised of 8 bits. position by 8. This is because each byte is comprised of 8 bits.
Example: int bitPos = bufferPos \* 8; e.g. `int bitPos = bufferPos * 8;`

7
src/Data.md Normal file
View File

@ -0,0 +1,7 @@
# Data
This section covers the raw data-related facilities and systems within the Client.
This includes an overview of the [data-types](./Data-Types.md) used, as well as
protocols like [JAGGRAB Protocol](./JAGGRAB-Protocol.md) and
[Ondemand Protocol](./Ondemand-Protocol.md).

View File

@ -16,9 +16,9 @@ A source of documentation for the RSC/RS2/RS3 protocols and related systems.
* [[RS3|Category RS3]] (2013 - present) * [[RS3|Category RS3]] (2013 - present)
### Cache ### Cache
* [[JAGGRAB|JAGGRAB Protocol]] * [JAGGRAB protocol](./JAGGRAB-Protocol.html)
* [[Ondemand|Ondemand Protocol]] * [Ondemand protocol](./Ondemand-Protocol.html)
* [[Archive Format]] * [Archive format](./Archive-Format.html)
### Miscellaneous ### Miscellaneous

View File

@ -1,48 +1,54 @@
\[\[Category Cache\]\] # JAGGGRAB protocol
== Introduction == # Introduction
The JAGGRAB protocol is used to 'grab' cache files from the file server In the early days of the client, it was distributed as an embedded
and download them. JAR within a web page.
So, reloading the web page would result in the user being served an up-to-date
client.
However, the cache files were stored locally and thus required a separate
mechanism for updating.
The JAGGRAB protocol addresses this by updating the client's cache files.
It does this by 'grabbing' cache files from the file server and downloading them.
It is a text-based protocol, similar to HTTP/0.9, and the client will It is a text-based protocol, similar to HTTP/0.9, and the client will
fall back to HTTP if JAGGRAB is unavailable. This generally happens in fall-back to HTTP if JAGGRAB is unavailable. This generally happens in
unsigned mode and helps users who are behind firewalls. unsigned mode and helps users who are behind firewalls.
== Request format == ## Request format
A request is simply the text JAGGRAB, a space, the path to the file and A request is simply the text JAGGRAB, a space, the path to the file and
a newline character. Therefore, it is very similar to a HTTP/0.9 GET a newline character. Therefore, it is very similar to a HTTP/0.9 GET
request. request.
JAGGRAB /path/to/file e.g. `JAGGRAB /path/to/file`.
=== New engine === Note: In possibly all new engine clients, the client prefixes the JAGGRAB
In (perhaps all) new engine clients, the client prefixes the JAGGRAB
request line with a single byte (value 17). request line with a single byte (value 17).
== Response format == ## Response format
The response is simply the raw file data. Once the response is sent, the The response is the file bytes. Once the response is sent, the connection
connection is closed. is closed.
== Files == ## Files
There are a number of files which map to files in the cache. There are a number of files which map to files in the cache.
- '''/crc''' - the CRC table - `/crc` - the CRC table
- '''/title''' - cache 0, file 1 - `/title` - cache 0, file 1
- '''/config''' - cache 0, file 2 - `/config` - cache 0, file 2
- '''/interface''' - cache 0, file 3 - `/interface` - cache 0, file 3
- '''/media''' - cache 0, file 4 - `/media` - cache 0, file 4
- '''/versionlist''' - cache 0, file 5 - `/versionlist` - cache 0, file 5
- '''/textures''' - cache 0, file 6 - `/textures` - cache 0, file 6
- '''/wordenc''' - cache 0, file 7 - `/wordenc` - cache 0, file 7
- '''/sounds''' - cache 0, file 8 - `/sounds` - cache 0, file 8
NOTE: the client will usually postfix these with random numbers, so when Note: the client will usually postfixes these with random numbers, so when
checking for the file only the start of the string should be examined: checking for the file only the start of the string should be examined:
not the whole one. This is to help avoid caches when these files are not the whole one.
fetched over HTTP.<BR> NOTE: The crc is postfixed with the client This is to help avoid caches when these files are fetched over HTTP.
revision
Note: The crc is postfixed with the client revision.

View File

@ -1,10 +1,17 @@
\[\[Category RSC\]\] # 0B3
This page refers to .ob3, a custom format for 3D models created by This page documents the `.ob3` format, a bespoke format for 3D models
Jagex. It is used by the RuneScape Classic engine since client version created by Jagex.
\#74. For the earlier version of the format see \[\[OB2\|OB2\]\]. It is used by the RuneScape Classic engine since client version
\#74.
<pre>public class OB3Model { Note: There is also an earlier version of this format called `.ob2`.
## OB3 Model Class
The following is the fully renamed client code used to represent OB3 models.
```java
public class OB3Model {
private static final int num_seq = 0xbc614e; // 12345678 private static final int num_seq = 0xbc614e; // 12345678
public int vertex_count; public int vertex_count;
@ -104,26 +111,29 @@ Jagex. It is used by the RuneScape Classic engine since client version
return i; return i;
} }
} }
</pre> ```
== '''Faces''' == A '''negative''' face\_fill\_back or face\_fill\_front
value indicates a '''solid colour''', whereas a'''positive''' value
indicates a '''texture'''. The texture is defined by its offset in the
client's texture array.
When converting to/from ## Faces
\[http://en.wikipedia.org/wiki/Wavefront\_.obj\_file Wavefront OBJ\]
A negative face_fill_back or face_fill_front value indicates a solid colour, whereas a positive value indicates a texture.
The texture is defined by its offset in the client's texture array.
When converting to/from [Wavefront OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
format, remember that the OB3 face vertices are one less than the OBJ format, remember that the OB3 face vertices are one less than the OBJ
face vertices. face vertices.
<pre>public static int decode_colour(int i) { The below code will allow you to encode or decode colours in this format.
```java
public static int decode_colour(int i) {
i = -(i + 1); i = -(i + 1);
int r = i >> 10 & 0x1f; int r = i >> 10 & 0x1f;
int g = i >> 5 & 0x1f; int g = i >> 5 & 0x1f;
int b = i & 0x1f; int b = i & 0x1f;
return (r << 19) + (g << 11) + (b << 3); return (r << 19) + (g << 11) + (b << 3);
} }
</pre>
<pre>public static int encode_colour(int r, int g, int b) { public static int encode_colour(int r, int g, int b) {
return -1 - (r / 8) * 1024 - (g / 8) * 32 - b / 8; return -1 - (r / 8) * 1024 - (g / 8) * 32 - b / 8;
} }
</pre> ```

View File

@ -1,28 +1,34 @@
\[\[Category Cache\]\] # Ondemand protocol
== Introduction == The Ondemand protocol is used to stream updates to the cache.
The client knows which files to update from the CRC file downloaded
using the [JAGGRAB Protocol](./JAGGRAB-Protocol.html).
The 'Ondemand' protocol is used to stream updates to the cache. The ## Request format
client knows which files to update from the CRC file downloaded using
the \[\[JAGGRAB Protocol\|JAGGRAB protocol\]\].
== Request packet ==
The client first authenticates as an ondemand client by using the opcode The client first authenticates as an ondemand client by using the opcode
'15' (as opposed to the game, which uses the type '14'). '15' (as opposed to the game, which uses the type '14').
The format of the request is: The format of the request is:
unsigned byte cacheId; unsigned short fileId; unsigned byte priority; ```
unsigned byte cacheId;
unsigned short fileId;
unsigned byte priority;
```
There can be multiple requests per session. Furthermore, there can be multiple requests per session.
== Response packet == ## Response format
The response is sent in blocks. The maximum size of a block is 500 The response is sent in blocks. The maximum size of a block is 500
bytes. Smaller blocks (at the end of a file) are permitted. bytes. Smaller blocks (e.g. towards the end of a file) are permitted.
Each block has the format: The format of a block is:
```
unsigned byte cacheId; unsigned short fileId; unsigned short fileSize; unsigned byte cacheId;
unsigned byte blockNumber; unsigned byte\[\] blockData; unsigned short fileId;
unsigned short fileSize;
unsigned byte blockNumber;
unsigned byte[] blockData;
```

View File

@ -1,3 +1,4 @@
A "QWord" (quad-word) is a data-type that consists of 8 bytes.<br /> It # QWord
is also commonly known as the "long" data-type in programming.
\[\[Category Data Type\]\] A "QWord" (quad-word) is a data-type that consists of 8 bytes.
It is also commonly known as the "long" data-type in programming.

View File

@ -1,11 +1,15 @@
== Introduction == # RS String
RS String is a codename for a custom string data-type used in the RS String is the internal name for a custom string data-type used in the
RuneScape protocol. <br /> The string data-type is used to hold a series RuneScape protocol.
of characters in order to form a message. The string data-type stores a collection of characters in order to
represent a textual message.
===Old Engine Protocol=== In the old engine client, the RS String ## Old Engine
datatype is delimited by a newline character (value "\n").
===New Engine Protocol=== In the new-engine client, the RS String In the old engine client, the RS String datatype is terminated by the new line
datatype is delimited by a null byte (value 0). character (i.e. `\n`).
# New Engine
In the new-engine client, the RS String datatype is terminated by a null byte (i.e. `0`).

View File

@ -7,18 +7,20 @@
- [General disclaimer](./General-disclaimer.md) - [General disclaimer](./General-disclaimer.md)
- [DMCA policy](./DMCA-policy.md) - [DMCA policy](./DMCA-policy.md)
- [Privacy policy](./Privacy-policy.md) - [Privacy policy](./Privacy-policy.md)
- [Archive-Format](./Archive-Format.md) - [Data](./Data.md)
- [Data-Types](./Data-Types.md)
- [Word](./Word.md)
- [DWord](./DWord.md)
- [QWord](./QWord.md)
- [RS String](./RS-String.md)
- [JAGGRAB protocol](./JAGGRAB-Protocol.md)
- [Ondemand protocol](./Ondemand-Protocol.md)
- [Archive format](./Archive-Format.md)
- [OB3](./OB3.md)
- [Class-Check](./Class-Check.md) - [Class-Check](./Class-Check.md)
- [Data-Types](./Data-Types.md)
- [DWord](./DWord.md)
- [JAGGRAB-Protocol](./JAGGRAB-Protocol.md)
- [Map-Region-System](./Map-Region-System.md) - [Map-Region-System](./Map-Region-System.md)
- [OB3](./OB3.md)
- [Ondemand-Protocol](./Ondemand-Protocol.md)
- [QWord](./QWord.md)
- [RS-String](./RS-String.md) - [RS-String](./RS-String.md)
- [Template-Packet](./Template-Packet.md) - [Template-Packet](./Template-Packet.md)
- [Word](./Word.md)
- [135-Protocol](./135-Protocol.md) - [135-Protocol](./135-Protocol.md)
- [194-Clear-screen](./194-Clear-screen.md) - [194-Clear-screen](./194-Clear-screen.md)
- [194-Logout](./194-Logout.md) - [194-Logout](./194-Logout.md)

View File

@ -1,3 +1,4 @@
A "word" is a data-type that consists of 2 bytes. <br /> It is also # Word
commonly known as the "short" data-type in programming. \[\[Category
Data Type\]\] A "word" is a data-type that consists of 2 bytes.
It is also commonly known as the "short" data-type in programming.