As I've decided to kinda write a new source in D, then I wanted to finish the packet structures before starting to write the server. I will be updating this thread with packet structures as I get further in development.
This could be used for people who might be interested in D, the packet structures (Although not offset based.) etc.
All packets will be based on patch 5515-5518 or any patches around there. In the future I might use the conditional compilation to have different versions for offsets. Gotta love D's version keyword.
Note: None of the packets has been tested in terms of server usage as of now, but they should be pretty much legit structures.
Packet writer/reader: (packet.d)
Code:
module packet;
import std.c.string;
version (Windows) {
private const string newLine = "\r\n";
}
else {
private const string newLine = "\n";
}
enum PacketType : ushort {
// Auth Packets ...
authrequest = 1086,
authresponse = 1055,
passwordseed = 1059,
// Game Packets ...
authmessage = 1052,
message = 1004
}
/**
* A data packet class.
*/
class DataPacket {
protected:
/**
* The data packet buffer.
*/
ubyte[] b;
/**
* The current read offset.
*/
size_t offset = 0;
/**
* Creates a new instance of DataPacket.
*/
this() { }
public:
/**
* Creates a new instance of DataPacket.
*/
this(ushort type, ushort size) {
assert(size < 1024);
write!ushort(size);
write!ushort(type);
}
/**
* Creates a new instance of DataPacket.
*/
this(ubyte[] buffer) {
assert(buffer !is null);
assert(buffer.length > 4);
b = buffer.dup;
}
/**
* Creates a new instance of DataPacket.
*/
this(DataPacket packet) {
assert(packet !is null);
assert(packet.plength > 4);
b = packet.b.dup;
}
/**
* Appends bytes to the buffer.
*/
void writeBuffer(ubyte[] buffer) {
b ~= buffer;
}
/**
* Writes an empty buffer until the specific offset.
*/
void writeEmpty(size_t toOffset) {
while (b.length < toOffset)
write!ubyte(0);
}
/**
* Writes a value to the buffer.
*/
void write(T)(T value) {
ubyte[] pBuffer = new ubyte[T.sizeof];
auto ptr = &value;
memcpy(pBuffer.ptr, ptr, T.sizeof);
writeBuffer(pBuffer);
}
/**
* Writes a string value to the buffer.
*/
void writeString(string value) {
writeBuffer(cast(ubyte[])value);
}
/**
* Reads a value from the buffer.
*/
auto read(T)() {
ubyte[] pBuffer = b[offset .. (offset + T.sizeof)];
T val;
memcpy(&val, pBuffer.ptr, T.sizeof);
offset += T.sizeof;
return val;
}
/**
* Reads a buffer value.
*/
ubyte[] readBuffer(size_t size) {
ubyte[] pBuffer = b[offset .. (offset + size)];
offset += size;
return pBuffer;
}
/**
* Reads a string value.
*/
string readString(size_t size) {
return cast(string)readBuffer(size);
}
/**
* Skips offsets for reading.
*/
void skip(size_t offsets = 1) {
offset += offsets;
}
/**
* Goes to a specific offset for reading.
*/
void go(size_t offset) {
this.offset = offset;
}
@property {
/**
* Gets the final buffer.
*/
ubyte[] buffer() {
ushort vlen = vlength;
while (b.length != vlen) {
write!ubyte(0);
}
return b;
}
/**
* Gets the physical length of the packet.
*/
size_t plength() {
return b.length;
}
/**
* Gets the virtual length of the packet.
*/
ushort vlength() {
size_t oldOffset = offset;
offset = 0;
ushort size = read!ushort;
offset = oldOffset;
return size;
}
/**
* Gets the packet type.
*/
ushort ptype() {
size_t oldOffset = offset;
offset = 2;
ushort p = read!ushort;
offset = oldOffset;
return p;
}
}
/**
* Gets the string of the packet.
*/
override string toString() {
import std.conv : to;
import std.string : format;
string s = format("Packet: %s P-Size: %s V-Size: %s", ptype, plength, vlength);
s ~= newLine;
s ~= "bytes[";
foreach (v; b) {
s ~= "0x" ~ to!string(v, 16) ~ ", ";
}
s.length -= 2;
s ~= "]";
s ~= newLine;
s ~= "text('";
foreach (v; b) {
s ~= (v >= 32 && v <= 126 ? cast(char)v : '.');
}
return s ~ "')";
}
}
/**
* A string packer class.
*/
class StringPacker {
public:
static:
/**
* Packs the strings into a packet.
*/
void pack(DataPacket packet, string[] strings) {
packet.write!ubyte(cast(ubyte)strings.length);
foreach (s; strings) {
if (s) {
packet.write!ubyte(cast(ubyte)s.length);
if (s.length)
packet.writeString(s);
}
else
packet.write!ubyte(0);
}
}
/**
* Unpacks strings from a packet.
*/
string[] unpack(DataPacket packet) {
string[] strings;
ubyte stringCount = packet.read!ubyte;
foreach (i; 0 .. stringCount) {
ubyte stringSize = packet.read!ubyte;
if (stringSize > 0) {
strings ~= packet.readString(stringSize);
}
else
strings ~= null;
}
return strings;
}
}
I fancied the idea of XML packet structures for versioning. A server, built once, could handle any client it has the structures for.
D is an interesting language.. what made you look into it?
I really like Haskell, but I fear it.. haha, I think I'm not smart enough to use the language. My professor knows the language and he explains it to be very robust for the sort of things I'm interested in.. Much more over C#, which is what I use now.
I fancied the idea of XML packet structures for versioning. A server, built once, could handle any client it has the structures for.
D is an interesting language.. what made you look into it?
I really like Haskell, but I fear it.. haha, I think I'm not smart enough to use the language. My professor knows the language and he explains it to be very robust for the sort of things I'm interested in.. Much more over C#, which is what I use now.
The only problem with the xml idea would be performance decrease and you really only want your server to run on specific patches and not a range of patches, because of feature changes between them.
I looked into D, because I wanted to learn a new language that I could use to build efficient thread-safe, concurrent applications such as web servers, so I dug into D with a focus on simple network programming and the structure of a webserver and really liked the language and its many features which most langauges today lack. Then I discovered vibe.d and got really hyped.
vibed.org
I started to use it as my main language and wrote a few interpreters and a simple language that compiled to C then to native, wrote an extension to the sfml library for D to support GUI programming and simplified event handling and interaction between gaming and GUI.
Such as this.
Why would there be a performance decrease when using XML packet structures? You just use the xml to build or populate a class you're not reading from them continually just when the server starts...
Also the whole multi patch support isn't very easy to implement there's a whole range of changes beyond just packet structures that you would need to account for, I dropped the concept in the end as the amount of changes would basically require you to build a base and then use plugins for handling the different changes in logic. It would be an exceptional amount of work, basically.
[Release] BTRF reader/writer source 01/24/2017 - Rappelz Private Server - 20 Replies It was asked some time ago and Gr4ph0s asked too, for the source of the BTRF parser.
This project is a BTRF reader/writer that represent a model of these file. So it can write BTRF files, but you need to add data to blocks in order to write something in a file.
For more information about how to use it, see dll-client-cpp/main.cpp and dll-client-python/print-content.py for a python script.
The code is made using C++, so I don't expect so much contribution, but if someone want to...
Bin READER / WRITER [SOURCE] 04/06/2013 - WarRock - 7 Replies Heyho,
Ich Release mal meine Decoder und Encoder Source für .bin Dateien.
Have fun :)
Multiupload.nl - upload your files to multiple file hosting sites!
Virustotal:
Packet Structures From XML 10/10/2011 - CO2 Private Server - 6 Replies Not sure, if it works nor if I have done it right, but it looks correct to me.
However would it be a good thing to read packet structures from a xml file like this or is there better ways?
The reason I'm interested in it, it's because you do not need to open source to edit offsets nor build, if an offset is wrong or something.
The wrapper:
public class PacketStructure
{
[Q]Packet Structures 06/18/2010 - Kal Online - 10 Replies any1 can help me with packet structures..? like
When I have packet like 0x11 or any other type.
Data is for example: 11 00 00 00 4A 58 9A 4A 32 ...
Where 4A 58 represents some WORD (coord, playerid, whatever)
etc.
thanks......