[Release] Simple Packet Writer

11/15/2012 00:43 Spirited#1
Hey everyone.

This was a request by a few friends of mine to make a simple, managed packet writer for C#. You can use it to create packets of all different styles. Using it is easy as well. I'll give you all a few examples of what it can do and how to use it in a minute. First, here's the download for the source code. You may also choose to download it in the form of a dll (which is available through my mediafire account).

Source Download: [Only registered and activated users can see links. Click Here To Register...]

Alright, so let's go over how to implement it. It's pretty easy. First, create a new class and inherit the packet structure class (like so):
PHP Code:
    // This is an example of a packet:
    
public class PacketName : PacketStructure
    
{
        public 
PacketName(byte[] receivedPacket)
            : 
base(receivedPacket)
        {
            
        }
    } 
Just by doing this, you've successfully implemented all of the methods from the Packet Structure class. You can now send your class as a byte array at any time. For example, if your character's send method accepts byte arrays, you don't need to do anything to send the packet as a byte array. My class does that implicitly (automatically). It will convert it to a byte array for you. If you wish to change the build method (maybe add some string building calls before finally building the packet), you can always override it by overriding the Build method.

Let's talk about constructing packets. You have two options. You can create your own to send to the client, or receive a packet from the client. Reading and Writing values is easy as well. I've supplied you with a variety of methods. I also gave my Write methods different names (on request) so you can easily see the type of value being written. Feel free to explore the class. I haven't tested it at all, so if you find an error, let me know.

Finally, here are a few examples of it in use:
[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] (Incomplete, just an example)

There are other things you can do as well. I hope this is what you guys asked for.
Cheers,
Spirited Fang.
11/15/2012 09:23 I don't have a username#2
Make a property for the pointer, so you don't need to declare it every time.

And a suggestion for WriteStringWithLength make it have an out parameter to spit out the next offset.

And WriteRandomInt, maybe consider doing a static random for the class and a thread-safe one.

I think that's it. Just skimmed through it fast.

#Edit got a last one. Make a constructor for setting a type/size of the packet, so it's not for reading or so you won't need to make a byte array and pass it as argument to it...

#Edit noticed another thing you said that you can send the class as a byte array, might reword that, because you don't send the class. You're using an implicit type-conversion from your packetwriter class to a byte array and it won't actually work. Have you tested it? Pretty sure it will say that you can't convert x to a byte array, where x is the class inheriting the packet writer, but if using the packet writer alone you can. I had that problem with earlier packet writers of mine, so actually you'd also have to create the 2 implicit operators within that instead of the base class only.
11/15/2012 12:52 nTL3fTy#3
I've tried to move away from explicitly defined offsets in packet structures. You never know if TQ is going to add new content in the middle of the packet structure and cause your packet structure beyond that new content's offset to become invalid.
11/15/2012 16:29 Spirited#4
Thanks for the suggestions. I'll keep them in mind. I don't actually use this in my project though. It was designed on request for the base I released. I'll add something that spits out the next offset for writing. I like that idea quite a lot. The random they can edit to work with their server. Again, thanks.

@nTLfTy: I write my packets for Kibou using sequential structures and an interface.
11/15/2012 22:05 go for it#5
good job fang , it need some work but basically it's good
keep it up
11/16/2012 16:00 Danial Eugen#6
Sorry but what is the use of type there ?

Code:
        public LoginPacket(int length, int type)
            : base(length, type)
        {
        }
i tried to send a packet using your class and whatever type i use does not matter in the packet mmm.
11/16/2012 17:35 Spirited#7
Quote:
Originally Posted by Danial Eugen View Post
Sorry but what is the use of type there ?

Code:
        public LoginPacket(int length, int type)
            : base(length, type)
        {
        }
i tried to send a packet using your class and whatever type i use does not matter in the packet mmm.
You're not supposed to have the length and type in the constructor of the packet itself, only in the base constructor. I should also say that this packet writer is aimed at 5017 and below. "base" is my class, the class you inherited. You inherited it into your own packet class to help you construct and manage the packet. Look at the example I provided.
11/16/2012 19:54 Danial Eugen#8
I rewrote your class using Binary Reader\Writer but i got kinda screwed problem that the write string method adds white spaces to the value

Here is the class without the use of pointers [still non complete]

11/16/2012 21:24 Spirited#9
Quote:
Originally Posted by Danial Eugen View Post
I rewrote your class using Binary Reader\Writer but i got kinda screwed problem that the write string method adds white spaces to the value

Here is the class without the use of pointers [still non complete]
Why are you using the old version that I didn't even release here? Use the version from this thread. And with the string method, it's supposed to write white space. It clears the previous value out from the packet so it doesn't get corrupted (hence why I ask for the maximum string length).

EDIT: Oh, I see. You just severely edited it to make it look like the one in the base I gave out (which is completely managed). I would highly recommend you don't do that. My writer is much more efficient than that.
11/16/2012 21:39 Danial Eugen#10
Quote:
Originally Posted by Fаng View Post
Why are you using the old version that I didn't even release here? Use the version from this thread. And with the string method, it's supposed to write white space. It clears the previous value out from the packet so it doesn't get corrupted (hence why I ask for the maximum string length).
Is that your old one ?

This one i just wrote myself depending on your class layout...
11/16/2012 21:41 Spirited#11
You responded before I saved my edit.

"Oh, I see. You just severely edited it to make it look like the one in the base I gave out (which is completely managed). I would highly recommend you don't do that. My writer is much more efficient than that."

I recommend you don't do what you're doing. If you want sequential packet construction, use a struct and pointers. Besides, how are you going to write over fields when you need to later in processing with that? You can't specify offsets to write to.
11/16/2012 21:44 Danial Eugen#12
Quote:
Originally Posted by Fаng View Post
You responded before I saved my edit.

"Oh, I see. You just severely edited it to make it look like the one in the base I gave out (which is completely managed). I would highly recommend you don't do that. My writer is much more efficient than that."

I recommend you don't do what you're doing. If you want sequential packet construction, use a struct and pointers. Besides, how are you going to write over fields when you need to later in processing with that? You can't specify offsets to write to.
I don't know about the base you are talking about i was editing your class without any background to make it looks like. Also about the offset i just finished creating a Seek function [that will move the writing\reading position to the specified one] but i wonder why you are saying that Pointers are more efficient than Binary Writer\Reader ?
11/16/2012 23:43 Spirited#13
Quote:
Originally Posted by Danial Eugen View Post
I don't know about the base you are talking about i was editing your class without any background to make it looks like. Also about the offset i just finished creating a Seek function [that will move the writing\reading position to the specified one] but i wonder why you are saying that Pointers are more efficient than Binary Writer\Reader ?
Well.... let's think about this. There's my method which just reads from a memory location using a pointer... and then we're comparing that to the binary reader (for now) defined under the .NET framework. The binary reader works by first encoding the stream its handling (already less efficient than just accepting the byte array for my constructor). Then, (since you're asking about the method I use vs. their method), their method calls on the memory stream's readInt32 method which: (1) increments the position it's at using a temporary integer, comparison, and assignment (less efficient than my checking), and (2) uses an algorithm to get the integer from the buffer (less efficient than just getting the pointer of the byte array and getting the value at the address). So yes, I'm prepared to say that my packet writer (which was designed for packet writing and reading) is more efficient than a binary writer (which was designed for stream writing).
11/16/2012 23:50 Danial Eugen#14
Quote:
Originally Posted by Fаng View Post
Well.... let's think about this. There's my method which just reads from a memory location using a pointer... and then we're comparing that to the binary reader (for now) defined under the .NET framework. The binary reader works by first encoding the stream its handling (already less efficient than just accepting the byte array for my constructor). Then, (since you're asking about the method I use vs. their method), their method calls on the memory stream's readInt32 method which: (1) increments the position it's at using a temporary integer, comparison, and assignment (less efficient than my checking), and (2) uses an algorithm to get the integer from the buffer (less efficient than just getting the pointer of the byte array and getting the value at the address). So yes, I'm prepared to say that my packet writer (which was designed for packet writing and reading) is more efficient than a binary writer (which was designed for stream writing).
Well seems legit! you persuaded me :D. so you are speaking about speed too...

Could you mention the drawbacks you consider in this PacketLiberary you posted so i can have the time fixing them ? or\and the things that it needs {from your point of view}
11/17/2012 00:12 Spirited#15
Quote:
Originally Posted by Danial Eugen View Post
Well seems legit! you persuaded me :D. so you are speaking about speed too...

Could you mention the drawbacks you consider in this PacketLiberary you posted so i can have the time fixing them ? or\and the things that it needs {from your point of view}
Well, I disagree with this method of writing packets. I use structs and pointers to write and handle my packets. If you like this style of writing packets though (I have to admit, it makes the concept a lot easier to understand at first), then there's no problem with that.

Answering your question though, things that can be improved... There's a lot. You could manage the memory instead of using a managed byte array (however, that's too much for something like this). I would just leave it as it is really. You could add a few methods here and there if you'd like. Make better get hash and string methods and such. It's really up to you. Here's a method you can add if you'd like (as an example):

Code:
using System.Drawing;
Code:
        /// <summary> This method returns a color from the packet at the specified offset. </summary>
        /// <param name="offset">The position at which the reader will read from.</param>
        /// <returns>The color read from the packet at the specified offset.</returns>
        public Color ReadColor(int offset)
        {
            // Error check the length:
            if (offset + 4 > _array.Length)
                throw new IndexOutOfRangeException("Attempted to read out of the bounds of the packet array.");

            // Read the value:
            fixed (byte* ptr = _array)
                return *(Color*)(ptr + offset);
        }
Code:
        /// <summary> This method writes a color to the packet structure. </summary>
        /// <param name="value">The value being written to the packet.</param>
        /// <param name="offset">The position where the value will be written to.</param>
        public void WriteColor(Color value, int offset)
        {
            // Error check the length:
            if (offset + 4 > _array.Length)
                throw new IndexOutOfRangeException("Attempted to write out of the bounds of the packet array.");

            // Write the value:
            fixed (byte* ptr = _array)
                *(Color*)(ptr + offset) = value;
        }