Register for your free account! | Forgot your password?

You last visited: Today at 10:03

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



[Release]Extremely Basic 5017 Source

Discussion on [Release]Extremely Basic 5017 Source within the CO2 PServer Guides & Releases forum part of the CO2 Private Server category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Jun 2013
Posts: 41
Received Thanks: 4
[Release]Extremely Basic 5017 Source

This is just a very basic source that I have been working on. Looking for some suggestions, so thought that I would throw it up here for some feedback. My main focus has been on the SQL system and making the query times very quick and cost efficient. Mainly looking for ideas in regards to threading. I know using too many threads is very inefficient, yet I don't like constantly checking timestamps on buffs to see if they need to be removed. Any ideas or suggestions would be greatly appreciated.


Credits:
Infamous and CptSky for Cryptography/Socket System
Attached Files
File Type: rar Emulator.rar (1.46 MB, 348 views)
FatalError- is offline  
Thanks
1 User
Old 06/30/2013, 02:58   #2
 
U2_Caparzo's Avatar
 
elite*gold: 0
Join Date: Aug 2011
Posts: 314
Received Thanks: 90
well, i just checked it using notepad since i don't have my laptop rigth now(hard to look in details without an IDE :c) but the first thing i saw was that you are creating an infinite loop in a thread from the ThreadPool, try to avoid this since that pool is supposed to be used by other .net applications too, not that -1 thread could cause a big impact, but it's a bad practice.
you are also using a thread-safe wrapper for the Dictionary class, when u could use a ConcurrentDictionary, i haven't tested yet but i suppose that ConcurrentDictionary only need to 'lock' when a remove or a loop is being executed, while the wrapper of the dictionary needs to lock when you are adding a pair too.
I saw that u are using a Stopwatch to do some checks, it's something i have thougth a lot too since DateTime lacks of precision, have not found anything against it
I kinda dislike too(just personal opinion)the way that u have splitted the packets in ToReceive and ToSend when could have only one class with the methods needed, it looks a bit disorganized(if exists that word O.o), for example this is how I LIKE, emphasis in the I xd to have the packets
Code:
class AuthorizationResponse : IServerPacket
    {
        private static readonly NetPacketHeader Header = new NetPacketHeader()
        {
            Length = 32,
            ID = 1055
        };
        public uint UID;
        public AccountPermission Authorization;
        public string MsgServerIP = "SERVER_IP";//configuration
        public int MsgServerPort = SERVER_PORT;//configuration

        public NetPacket Serialize()
        {
            NetPacket packet = new NetPacket(Header, false);
            packet.WriteUInt32(UID);
            packet.WriteUInt32((uint)Authorization);
            packet.WriteString(MsgServerIP, 16);
            packet.WriteInt32(MsgServerPort);
            return packet;
        }
    }
IServerPacket is an interface that make the packet's class have a Serialize method, or what is your ToSend folder, or something like that xd.
i also have an interface called IClientPacket, that will be the ToReceive folder idea too, with the methods Deserialize and Process like this
Code:
    public class AuthorizationRequest : IClientPacket
    {
        public string Account;
        public string Password;
        public string ServerName;

        public void Deserialize(NetPacket packet)
        {
            packet.Seek(4, SeekOrigin.Begin);
            Account = packet.ReadString(16).TrimEnd('\0', ' ');
            Password = packet.ReadString(16).TrimEnd('\0', ' ');
            ServerName = packet.ReadString(16).TrimEnd('\0', ' ');
            packet.Dispose();
        }

        public void Process(object sender)
        {
            AuthClient client = sender as AuthClient;
            IServerPacket response = new AuthorizationResponse();
            try
            {
                using (MySqlReader reader = new MySqlReader())
                {
                    reader.Select("accounts");
                    reader.WhereMatch("account", Account);
                    reader.Execute();
                    string realPassword = PasswordCryptography.EncryptPassword(reader.ReadString("password"));
                    client.UID = reader.ReadUInt32("uid");
                    response.UID = client.UID;
                    if (LoginExploits.AccountClients.ContainsKey(response.UID))
                        client.Disconnect();
                    AccountPermission permission = (AccountPermission)reader.ReadByte("state");
                    switch (permission)
                    {
                        case AccountPermission.Moderator:
                        case AccountPermission.ProjectManager:
                        case AccountPermission.Normal:
                            response.Authorization = AccountPermission.Normal;
                            break;
                        case AccountPermission.Banned:
                        case AccountPermission.Unactivated:
                            response.Authorization = permission;
                            break;
                        default:
                            response.Authorization = AccountPermission.Error;
                            break;
                    }
                    if (response.Authorization == AccountPermission.Normal)
                    {
                        if(realPassword != Password)
                            response.Authorization = AccountPermission.Invalid;
                        
                    }
                    LoginExploits.AccountClients.Add(client.UID, client);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e);
                response.Authorization = AccountPermission.Invalid;
            }
            client.Send(response);
        }
    }
maybe not the best code, but an example of the 'concept' behind how i structure my packets.
hope helped a little bit
U2_Caparzo is offline  
Old 06/30/2013, 04:51   #3
 
elite*gold: 0
Join Date: Jun 2013
Posts: 41
Received Thanks: 4
I have actually tested the concurrent dictionary, and it's actually a bit slower then the method im using. Im not sure, but I believe its meant for much larger scaling, and will scale better, but isnt really useful in anything related to co servers. Thanks for the advice tho, will be looking into the thread situation and see which one will fit it best. You happen to know if a new thread, task/threading.timer, or Timers.timer would be better?
FatalError- is offline  
Old 06/30/2013, 08:07   #4
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
Any collection under System.Collections.Concurrent is designed to handle thread-safety up to a much larger scale yours probably will and I believe it will be faster when you start to use multiple threads that's accessing the same objects within the collection. That's because the collections does not use a global lock for itself, but a lock for each entry.

Ex. This is the TryAdd method for ConcurrentDictionary.
Code:
[__DynamicallyInvokable]
public bool TryAdd(TKey key, TValue value)
{
	if (key == null)
	{
		throw new ArgumentNullException("key");
	}
	TValue tValue;
	return this.TryAddInternal(key, value, false, true, out tValue);
}
Code:
private bool TryAddInternal(TKey key, TValue value, bool updateIfExists, bool acquireLock, out TValue resultingValue)
{
	int hashCode = this.m_comparer.GetHashCode(key);
	checked
	{
		ConcurrentDictionary<TKey, TValue>.Tables tables;
		bool flag;
		while (true)
		{
			tables = this.m_tables;
			int num;
			int num2;
			this.GetBucketAndLockNo(hashCode, out num, out num2, tables.m_buckets.Length, tables.m_locks.Length);
			flag = false;
			bool flag2 = false;
			try
			{
				if (acquireLock)
				{
					Monitor.Enter(tables.m_locks[num2], ref flag2);
				}
				if (tables != this.m_tables)
				{
					continue;
				}
				ConcurrentDictionary<TKey, TValue>.Node node = null;
				for (ConcurrentDictionary<TKey, TValue>.Node node2 = tables.m_buckets[num]; node2 != null; node2 = node2.m_next)
				{
					if (this.m_comparer.Equals(node2.m_key, key))
					{
						if (updateIfExists)
						{
							if (ConcurrentDictionary<TKey, TValue>.s_isValueWriteAtomic)
							{
								node2.m_value = value;
							}
							else
							{
								ConcurrentDictionary<TKey, TValue>.Node node3 = new ConcurrentDictionary<TKey, TValue>.Node(node2.m_key, value, hashCode, node2.m_next);
								if (node == null)
								{
									tables.m_buckets[num] = node3;
								}
								else
								{
									node.m_next = node3;
								}
							}
							resultingValue = value;
						}
						else
						{
							resultingValue = node2.m_value;
						}
						return false;
					}
					node = node2;
				}
				Volatile.Write<ConcurrentDictionary<TKey, TValue>.Node>(ref tables.m_buckets[num], new ConcurrentDictionary<TKey, TValue>.Node(key, value, hashCode, tables.m_buckets[num]));
				tables.m_countPerLock[num2]++;
				if (tables.m_countPerLock[num2] > this.m_budget)
				{
					flag = true;
				}
			}
			finally
			{
				if (flag2)
				{
					Monitor.Exit(tables.m_locks[num2]);
				}
			}
			break;
		}
		if (flag)
		{
			this.GrowTable(tables);
		}
		resultingValue = value;
		return true;
	}
}
Super Aids is offline  
Thanks
1 User
Old 06/30/2013, 08:52   #5
 
elite*gold: 0
Join Date: Jun 2013
Posts: 41
Received Thanks: 4
Yeah, another thing i didn't like about it was the fact you always had to have an out parameter when your removing an item from the dictionary. Just annoying hah.
FatalError- is offline  
Old 06/30/2013, 09:59   #6
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
The out parameter is the value removed, it's actually useful in some cases.

Ex.
Code:
public bool Unequip(Enums.ItemLocation pos)
		{
			if (Owner.Inventory.Count < 40)
			{
				ItemInfo ritem;
				if (EquipmentItems.TryRemove(pos, out ritem))
				{
					Database.CharacterDatabase.SaveEquipment(Owner, null, pos);
					
					Owner.BaseEntity.CalculateBaseStats();

					using (var unequippack = new Packets.ItemPacket())
					{
						unequippack.UID = ritem.UID;
						unequippack.Action = Enums.ItemAction.Unequip;
						unequippack.Data1Low = (ushort)ritem.Location;
						Owner.Send(unequippack);
					}
					Owner.Inventory.AddItem(ritem);
					SendGears();
					return true;
				}
			}
			else
			{
				using (var fmsg = Packets.Message.MessageCore.CreateSystem2(Owner.Name, Core.MessageConst.INVENTORY_FULL))
					Owner.Send(fmsg);
			}
			return false;
		}
Otherwise you can just use extensions.
Code:
public static class Extensions
	{
		public static void Remove<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key)
		{
			TValue value;
			dict.TryRemove(key, out value);
		}
	}
Example Usage:
Code:
ConcurrentDictionary<int, string> dict = new ConcurrentDictionary<int, string>();
			dict.TryAdd(100, "Hello World!");
			dict.Remove(100);
Super Aids is offline  
Thanks
1 User
Old 06/30/2013, 11:22   #7
 
elite*gold: 0
Join Date: Jun 2013
Posts: 41
Received Thanks: 4
Yeah just didn't understand why they didn't include a seperate method.
FatalError- is offline  
Old 06/30/2013, 13:18   #8
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
Why would they?
Super Aids is offline  
Thanks
1 User
Old 06/30/2013, 14:51   #9
 
_DreadNought_'s Avatar
 
elite*gold: 28
Join Date: Jun 2010
Posts: 2,225
Received Thanks: 868
Code:
                    case "newacct":
                        {
                            Database.Methods.NewAccount(Command[1], Command[2]);
                            break;
                        }
                    default: break;
"default: break;" isn't needed

Infact - Have you tried using reSharper? It really cleans things up.

Behold! Entry.cs with resharped!

PHP Code:
using System;
using System.Text;
using GameCore;
using GameCore.Enums;
using GameCore.Network;
namespace 
AuthServer
{
    public 
sealed class Entry
    
{
        public static 
ThreadSafeRandom Random = new ThreadSafeRandom();
        private static 
void Main()
        {
            
Console.Title "Auth Server";
            var 
authSocket = new NetworkSocket();
            
authSocket.OnDisconnect += AnnounceDisconnection;
            
authSocket.OnReceive += AnnounceReceive;
            
authSocket.OnConnect += AnnounceConnect;
            
authSocket.Listen(9958);
            
authSocket.Accept();

            
Console.WriteLine("Listening for New Connections...");

            while (
true)
            {
                var 
readLine Console.ReadLine();
                if (
readLine != null)
                {
                    
string[] command readLine.Split(' ');
                    switch (
command[0])
                    {
                        case 
"newacct":
                            {
                                
Database.Methods.NewAccount(command[1], command[2]);
                                break;
                            }
                    }
                }
            }
        }
        private static 
void AnnounceConnect(NetworkClient client)
        {
            
Console.WriteLine("New Connection. IP: ( {0} )"client.IP);
        }
        private static 
void AnnounceDisconnection(NetworkClient client) { }

        private static 
void AnnounceReceive(NetworkClient clientbyte[] data)
        {
            var 
crypto = new GameCore.Cryptography.Cryptographer();
            
crypto.Decrypt(ref data);
            
ushort packetId BitConverter.ToUInt16(data2);
            if (
packetId == 1051)
            {
                
string account Encoding.ASCII.GetString(data416).Replace("\0""");
                
byte[] passBytes = new byte[16];
                
Buffer.BlockCopy(data20passBytes016);
                
string password GameCore.Cryptography.RC5.Decrypt(passBytes);

                
uint uniqueId 0;
                
AuthResponseType art Database.Methods.Authenticate(accountpasswordref uniqueId);
                
client.Crypto = new GameCore.Cryptography.Cryptographer();
                
byte[] pkt Packets.AuthResponse(Settings.IPartuniqueId);
                
client.Send(pkt);
                
client.Disconnect();
            }
            else
                
client.Disconnect();
        }
    }

Hmm - I don't like how you have to write each query out for any mysql interaction, I would much rather you come up with an easy to use system

_DreadNought_ is offline  
Thanks
1 User
Old 06/30/2013, 14:56   #10


 
CptSky's Avatar
 
elite*gold: 0
Join Date: Jan 2008
Posts: 1,443
Received Thanks: 1,175
[QUOTE=_DreadNought_;23562124]
Code:
                    case "newacct":
                        {
                            Database.Methods.NewAccount(Command[1], Command[2]);
                            break;
                        }
                    default: break;
"default: break;" isn't needed

Some IDE might request a default case in switches (at least, in C++). It's a good practice to have a default case. (And if it shouldn't go inside, to put an assert).
CptSky is offline  
Thanks
2 Users
Old 06/30/2013, 18:42   #11
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
[quote=CptSky;23562246]
Quote:
Originally Posted by _DreadNought_ View Post
Code:
                    case "newacct":
                        {
                            Database.Methods.NewAccount(Command[1], Command[2]);
                            break;
                        }
                    default: break;
"default: break;" isn't needed

Some IDE might request a default case in switches (at least, in C++). It's a good practice to have a default case. (And if it shouldn't go inside, to put an assert).
I don't know any C# IDE's that requires it and the C# compiler for sure doesn't. However it's common in other languages as you already said ex. C++, D and such ... Not necessary in C# at least not with any of the popular IDE's Visual Studio, Mono and #Develop.
Super Aids is offline  
Old 12/13/2013, 12:58   #12
 
elite*gold: 0
Join Date: Dec 2013
Posts: 1
Received Thanks: 0
Yeahyeah, here i come sounding like the biggest noob ever. But how do you make a 5017 server compatible with windows 7 64bit?
MgHD is offline  
Old 12/13/2013, 21:44   #13
 
turk55's Avatar
 
elite*gold: 130
Join Date: Oct 2007
Posts: 1,655
Received Thanks: 705
Quote:
Originally Posted by MgHD View Post
Yeahyeah, here i come sounding like the biggest noob ever. But how do you make a 5017 server compatible with windows 7 64bit?
A 64 bit computer is able to run 32 bit and 64 bit programs, however a 32 bit computer can only run a 32 bit program.

So if you are trying to run a program on a 64 bit computer and get an error, the problem should not be that.
turk55 is offline  
Old 12/13/2013, 22:35   #14
 
Super Aids's Avatar
 
elite*gold: 0
Join Date: Dec 2012
Posts: 1,761
Received Thanks: 950
Quote:
Originally Posted by turk55 View Post
A 64 bit computer is able to run 32 bit and 64 bit programs, however a 32 bit computer can only run a 32 bit program.

So if you are trying to run a program on a 64 bit computer and get an error, the problem should not be that.
Actually it could be that some of the DLL files used in PInvoke are 64 bit such as msvcrt.dll but the program is 32bit, so when it tries to PInvoke it will throw an exception
Super Aids is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
[Release] Extremely basic (but working/bugless) C# Source
11/30/2012 - CO2 PServer Guides & Releases - 348 Replies
This pretty much has a very finite amount of stuff done in it. Specifically this is pretty much all thats in it. If your serious about trying to develop a server in C#, I suggest looking at this. There's a DLL also included (check the "bin" folder) which will need to be added as a reference. SocketNetwork.dll pretty much handles the socket-system and encryptions for you it is not packed or obfuscated if you would like to decompile it and take a look at it, be my guest. I included a folder...



All times are GMT +1. The time now is 10:03.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.