In this topic, i will try to explain the basics of creating a conquer online private server from 'scratch' :}
Before reading this i would suggest that you have to read these threads:


Now to work :}
REQUIREMENTS:
1. 1 brain
2. Novice to intermediate level of C# knowledge
3. 2 pounds of curiosity
4. 10 pounds of determination
5. 1 pound of intelligence
6. 4 pounds of creativity
7. Basic knowledge of assembly
Side-note: If you lack determination and - or curiosity, i recommend you to navigate away from this topic and download a public source instead
PROCEDURE:
Question: What is a 'server'?
Possible definitions for 'server' from wikipedia: Game server - Wikipedia, the free encyclopedia - Proxy server - Wikipedia, the free encyclopedia
After the 'server' concept is clear i hope that next steps will become easier to grasp
Question: What are the basic elements of creating a game-server?
1. Socket class to start communications between server and clients, please check the top of this topic.
2. Data packets sent between clients and server which contain data from-to server that are used to identify which action should the server take, eg. Create a new character.
3. Encryption algorithm that decrypts-encrypts packets sent from-to the server.
4. Anti-cheat engines to cease botters.
foreach(element Item in ServerElements)
{
Item.ExplainInDetail();
}
1. Socket class:
I think i should not go any deeper in asynchronous winsockets, tanelipe did the job well :}
2. Data packets:
Also these are here:
, credits to Korvacs.Side-note: Don't write each value in the packet manually, instead create a static BufferWriter class that will do the job for you every time with just some arguments that you provide, this will make the code a lot easier to read later on.
3. Encryption algorithm:
We know that tq's client always send the packets encrypted as any company would do, so the problem is we cannot get the real values in the packet because they are encrypted :{ , but no fear assembly professionals are here, this is where assembly comes in trying to find the call to the encryption algorithm used in altering these values, then comes reverse engineering to reverse this algorithm to change these values back to normal, if you would like to go deeper at this you can google it because this goes far off the scope of this topic, fortunately cryptographers are available from public sources
4. Anti-cheat engines:
Now we will assume that you got your server running, but members are always complaining about botters, what can you do?
There are 2 types of bots out there:
1. Bots that write the process memory, which are the most accurate bots when it comes to performance since they use values from the process, this can be avoided in some ways, one of them is to create a dynamic link library that will be hooked up to the client which checks if there are other applications which are writing process memory or not, of course some disadvantages of this is that you may accidentally disable one of the essential libraries that the client uses, you'll have to be define which libraries to allow and which not to allow.
2. Bots that use pixels to bot, those are quite useless since they don't use real values instead they would search for a color in the screen or something like that, these are not really harmful, but can be detected in a deprecated way of searching window names for something that contain : "bot" and other related keywords, this method works for most of them as most are public releases that contain these keywords in their window captions, i am not really sure of other methods to do this so i will keep that point to other members that have tried it.
Side-note: anti-cheat engines should preferably be programmed in C/C++ rather than C#, as applications that require .NET can be easily decompiled resulting in some exploits.
-- Class And Interface Implementation --
Now we should mark up our path to easily and efficiently code through our server, so we create some interfaces or abstract classes that will help us do this, our first interface would mark up basic server elements eg. players, npcs and monsters, we will call this interface IServerElement.cs
1. Every one of these elements require a unique identification number that shall never be a -ve number so the integer type that best suites us is uint and our first property shall look like this
2. Now we need to place each somewhere in the server, we need a map so after looking at map identifications, the integer type that best suites us is a ushortQuote:
uint Id { get; set; }
3. After setting the map of each element, we need to specify its location on the map, so we need two other properties to set and retrieve values of x-coordination and y-coordinationQuote:
ushort Map { get; set; }
4. Also we must consider effects, so we need a uint type integer for flags or effectsQuote:
ushort X { get; set; }
ushort Y { get; set; }
At last, this is how the IServerElement interface look like:Quote:
uint Flag { get; set; }
Code:
public interface IServerElement
{
uint Id { get; set; }
ushort Map { get; set; }
ushort X { get; set; }
ushort Y { get; set; }
uint Flag { get; set; }
}
Now you can specify another interface for each object that inherits this interface as well , eg. Npc
Code:
public interface INpc : IServerElement
{
//Here goes other variables that are not declared in the IServerElement interface
}
Afterwards, you can create database functions that will load objects' information using these interfaces without having to create classes that implement these interfaces yet, but sooner or later you will have to create these classes.
Example of the npc class:
Code:
public class Npc : INpc //Implements both the INpc interface and the IServerElement
{
private uint id;
public uint Id
{
get { return this.id; }
set { this.id = value; }
}
// So on with other properties. .
}
-- Packets Implementation --
Well we got our database running and loading functions working properly, i guess it is time to create packets. .
What does a server actually do is, it receives packets from clients, reads and handles them, then echoes them back to clients with the needed data to tell the client which action to do, for instance, show that this character is dead, show ghost effect, show thunder, so on. .
a server might also do mathematical operations when some skill packets asking the server to expose a client to damage, revive a character etc, the server might calculate how many stamina points to deduct from the character and sends a packet to the client with corresponding values to tell the user 'hey, you lost some stamina from that last skill' in graphical concepts by lowering the bar's value, here is a small chart to make it a bit easier:
As i mentioned before, writing values to a packet every time manually is annoying and takes hell a lot of time and is considered bad practice, best way is to use a static class with static functions that will do this for you by just some arguments that you pass to the function. .
I hope that InfamousNoone wouldn't mind me using his packet builder class to do this, but to make things clear i did not code this packet builder, it was coded by InfamousNoone, if you want to get that class, download his public source ConquerServer_Basic.
1. One-way Packets
Let's use this to implement some packets from the conquer wiki by Korvacs:
for instance, let's use the Npc spawn packet

Here we go, first instantiate our byte arrayQuote:
(ushort)Length: 20 || 0x14
(ushort)Type: 2030 || 0x7ee
(uint)NpcType
(ushort)X
(ushort)Y
(ushort)NpcSubType
(ushort)DirectionFacing
(uint)Flag
Next as the wiki says, we need to write the packet length to the packet, which is a ushort or UInt16Quote:
byte[] Packet = new byte[20] // 20 because the length of this packet is 20 bytes, explicitly stated by Korvacs in the wiki
Next is to write the packet type, another ushort type integer, value 2030 in decimal or 0x7ee in hexadecimalQuote:
PacketBuilder.WriteUInt16(20, Packet, 0); // Used InfamousNoone's packet builder to write this value at the first byte of the packet, note that a UInt16 takes 2 bytes so the next offset we should write to is 2
Next we will write the identification number of the Npc to the packet, which is in this time is a uint type integer or UInt32Quote:
PacketBuilder.WriteUInt16(0x7ee, Packet, 2);
Notice that a UInt32 will take 4 bytes, next is the x-coordinate and y-coordinate of the npc, ushort integer typesQuote:
PacketBuilder.WriteUInt32(<NPC ID>, Packet, 4);
We are almost there! 3 more values to go, NPC subtype, the type of texture this npc should look like, ushort integer typeQuote:
PacketBuilder.WriteUInt16(<X COORD>, Packet, 8);
PacketBuilder.WriteUInt16(<Y COORD>, Packet, 10);
Direction flag which is the direction this npc should point to, for more info about directions please search them.Quote:
PacketBuilder.WriteUInt16(<NPC TYPE>, Packet, 12);
Flag, the effect that should be associated to this Npc, uint integer typeQuote:
PacketBuilder.WriteUInt16(<DIRECTION>, Packet, 14);
We are done creating our first packet! you will have to continue other packets on your own.Quote:
PacketBuilder.WriteUInt32(<FLAG>, Packet, 16);
-- Introduction to Packet Interface Implementation --
Back to packets, most of the time it is preferred to create each packet stand-alone with its own class, that's why we'll use properties wrapping each variable of the packet, because we're not actually reading variables, we're reading values from the packet itself. .
Now we will create two different packet interfaces, one with read-write properties, other with read-only properties, why? some packets do not require writing, because they are just one sided, the Npc spawn packet is one of them, it is sent to the client from the server, but the client doesn't echo it back, so let our read-only interface be IPacket, the read-write IDuoPacket.
now each one should look like this
Code:
public interface IPacket
{
byte[] Packet { get; }
}
public interface IDuoPacket
{
byte[] Packet { get; set; }
}
There are several reasons, first is to make writing code faster, without having to type something like
Code:
NpcSpawn nPacket = new NpcSpawn(); Client.Send(nPacket.Packet);
Code:
void Send(IPacket pPacket)
{
Socket.Send(pPacket.Packet);
}
void Send(IDuoPacket dPacket)
{
Socket.Send(dPacket.Packet);
}
Code:
NpcSpawn nPacket = new NpcSpawn(); Client.Send(nPacket);
Anyhow, we have another reason, some packets would just go to the server to do something, but they are never echoed back, why do we need to write values to them? makes sense, huh
Back again to the Npc spawn packet, let's see how the full structure look like:
Code:
public class NpcSpawn : INpc, IPacket
{
private byte[] packet;
private ushort map;
public NpcSpawn()
{
packet = new byte[20];
PacketBuilder.WriteUInt16(20, packet, 0);
PacketBuilder.WriteUInt16(2030, packet, 2);
}
public uint Id
{
get { return BitConverter.ToUInt32(packet, 4); }
set { PacketBuilder.WriteUInt32(value, packet, 4); }
}
public ushort X
{
get { return BitConverter.ToUInt16(packet, 8); }
set { PacketBuilder.WriteUInt16(value, packet, 8); }
}
public ushort Y
{
get { return BitConverter.ToUInt16(packet, 10); }
set { PacketBuilder.WriteUInt16(value, packet, 10); }
}
public ushort Type
{
get { return BitConverter.ToUInt16(packet, 12); }
set { PacketBuilder.WriteUInt16(value, packet, 12); }
}
public ushort Direction
{
get { return BitConverter.ToUInt16(packet, 14); }
set { PacketBuilder.WriteUInt16(value, packet, 12); }
}
public uint Flag
{
get { return BitConverter.ToUInt32(packet, 16); }
set { PacketBuilder.WriteUInt32(value, packet, 16); }
}
public ushort Map
{
get { return this.map; }
set { this.map = value; }
}
public byte[] Packet
{
get { return this.packet; }
}
}
That's a one way packet, so we implemented the IPacket interface instead of IDuoPacket because this packet is never sent from the client to the server, we don't need to read anything, just send the written packet to the client.
2. Two-way Packets
Let's view a duo packet, let's use the GeneralData packet form the wiki
This packet can have many sub-types which are listed here:Quote:
(ushort)Length: 28 || 0x1c
(ushort)Type: 1010 || 0x3f2
(uint)Timer
(uint)EntityID
(uint)DataA
(ushort)DataB
(ushort)DataC
(ushort)enum("Data_Type")
(string)TQString

The reason this packet is a duo packet, is that it can be sent from the client with some parameters, which in this case we will just read it and do the corresponding action, else it can be instantiated at the server and sent to the client. .
Let's implement it in a class, taking into consideration that it might be already sent from the client, using overloaded constructors we can make this happen:
Code:
public class GeneralData : IDuoPacket
{
private byte[] packet;
public GeneralData() //Instantiated version
{
Packet = new byte[28]; // or 0x1c
PacketBuilder.WriteUInt16(1010, packet, 0);
}
public GeneralData(byte[] rPacket)
{
Packet = rPacket;
}
public byte[] Packet
{
get { return this.packet; }
set { this.packet = value; }
}
// we continue with properties implementing as we did in the NpcSpawn packet.
}
Okay, let's assume the client requests a direction change, and it is being processed, we got the received packet. .
Code:
GeneralData dPacket = new GeneralData(ReceivedPacket);
switch(dPacket.Enum)
{
case ChangeDirection:
// do whatever action needed.
break;
}
Shouts:
tanelipe: Good job explaining asynchronous sockets, thanks.
Korvacs: Amazing wiki, thanks.
InfamousNoone: I like your way of building packets, that inspired me, thanks.
spare2: Thanks for the chart idea






