/// <summary>
			/// Reads up ONE character iteration on the packet stream
			/// </summary>
			/// <param name="packet"></param>
			/// <param name="client"></param>
			public CreationCharacterData(GSPacketIn packet, GameClient client)
			{
				//unk - probably indicates customize or create (these are moved from 1.99 4 added bytes)
				if (client.Version >= GameClient.eClientVersion.Version1104)
					packet.ReadIntLowEndian();

				CharName = packet.ReadString(24);
				CustomMode = packet.ReadByte();
				EyeSize = packet.ReadByte();
				LipSize = packet.ReadByte();
				EyeColor = packet.ReadByte();
				HairColor = packet.ReadByte();
				FaceType = packet.ReadByte();
				HairStyle = packet.ReadByte();
				packet.Skip(3);
				MoodType = packet.ReadByte();
				packet.Skip(8);
				
				Operation = packet.ReadInt();
				var unk = packet.ReadByte();
				
				packet.Skip(24); //Location String
				packet.Skip(24); //Skip class name
				packet.Skip(24); //Skip race name
				
				var level = packet.ReadByte(); //not safe!
				Class = packet.ReadByte();
				Realm = packet.ReadByte();
				
				//The following byte contains
				//1bit=start location ... in ShroudedIsles you can choose ...
				//1bit=first race bit
				//1bit=unknown
				//1bit=gender (0=male, 1=female)
				//4bit=race
				byte startRaceGender = (byte)packet.ReadByte();
				Race = (startRaceGender & 0x0F) + ((startRaceGender & 0x40) >> 2);
				Gender = ((startRaceGender >> 4) & 0x01);
				SIStartLocation = ((startRaceGender >> 7) != 0);

				CreationModel = packet.ReadShortLowEndian();
				Region = packet.ReadByte();
				packet.Skip(1); //TODO second byte of region unused currently
				packet.Skip(4); //TODO Unknown Int / last used?

				Strength = packet.ReadByte();
				Dexterity = packet.ReadByte();
				Constitution = packet.ReadByte();
				Quickness = packet.ReadByte();
				Intelligence = packet.ReadByte();
				Piety = packet.ReadByte();
				Empathy = packet.ReadByte();
				Charisma = packet.ReadByte();

				packet.Skip(40); //TODO equipment
				
				var activeRightSlot = packet.ReadByte(); // 0x9C
				var activeLeftSlot = packet.ReadByte(); // 0x9D
				var siZone = packet.ReadByte(); // 0x9E
				
				// skip 4 bytes added in 1.99
				if (client.Version >= GameClient.eClientVersion.Version199 && client.Version < GameClient.eClientVersion.Version1104)
					packet.Skip(4);
				
				// New constitution must be read before skipping 4 bytes
				NewConstitution = packet.ReadByte(); // 0x9F


			}
		public void HandlePacket(GameClient client, GSPacketIn packet)
		{
			string accountName = packet.ReadString(24);

			if (log.IsDebugEnabled)
				log.DebugFormat("CharacterCreateRequestHandler for account {0} using version {1}", accountName, client.Version);

			if (!accountName.StartsWith(client.Account.Name))// TODO more correctly check, client send accountName as account-S, -N, -H (if it not fit in 20, then only account)
			{
				if (ServerProperties.Properties.BAN_HACKERS)
					client.BanAccount(string.Format("Autoban wrong Account '{0}'", accountName));

				client.Disconnect();
				return;
			}
			
			// Realm
			eRealm currentRealm = eRealm.None;
			if (accountName.EndsWith("-S")) currentRealm = eRealm.Albion;
			else if (accountName.EndsWith("-N")) currentRealm = eRealm.Midgard;
			else if (accountName.EndsWith("-H")) currentRealm = eRealm.Hibernia;

			
			// Client character count support
			int charsCount = client.Version < GameClient.eClientVersion.Version173 ? 8 : 10;
			bool needRefresh = false;
			
			for (int i = 0; i < charsCount; i++)
			{
				var pakdata = new CreationCharacterData(packet, client);
				
				// Graveen: changed the following to allow GMs to have special chars in their names (_,-, etc..)
				var nameCheck = new Regex("^[A-Z][a-zA-Z]");
				if (!string.IsNullOrEmpty(pakdata.CharName) && (pakdata.CharName.Length < 3 || !nameCheck.IsMatch(pakdata.CharName)))
				{
					if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player)
					{
						if (ServerProperties.Properties.BAN_HACKERS)
							client.BanAccount(string.Format("Autoban bad CharName '{0}'", pakdata.CharName));

						client.Disconnect();
						return;
					}
				}
					
				switch ((eOperation)pakdata.Operation)
				{
					case eOperation.Delete:
						if (string.IsNullOrEmpty(pakdata.CharName))
						{
							// Deletion in 1.104+ check for removed character.
							needRefresh |= CheckForDeletedCharacter(accountName, client, i);
						}
						break;
					case eOperation.Customize:
						if (!string.IsNullOrEmpty(pakdata.CharName))
						{
							// Candidate for Customizing ?
							var character = client.Account.Characters != null ? client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;
							if (character != null)
								needRefresh |= CheckCharacterForUpdates(pakdata, client, character);
						}
						break;
					case eOperation.Create:
						if (!string.IsNullOrEmpty(pakdata.CharName))
						{
							// Candidate for Creation ?
							var character = client.Account.Characters != null ? client.Account.Characters.FirstOrDefault(ch => ch.Name.Equals(pakdata.CharName, StringComparison.OrdinalIgnoreCase)) : null;
							if (character == null)
								needRefresh |= CreateCharacter(pakdata, client, i);
						}
						break;
					default:
						break;
				}
			}
			
			if(needRefresh)
			{
				client.Out.SendCharacterOverview(currentRealm);
			}
		}
		public void HandlePacket(GameClient client, GSPacketIn packet)
		{
			string accountName = packet.ReadString(24);

			log.Debug("CharacterCreateRequestHandler for account " + accountName + " using version " + client.Version);

			if (!accountName.StartsWith(client.Account.Name))// TODO more correctly check, client send accountName as account-S, -N, -H (if it not fit in 20, then only account)
			{
				if (ServerProperties.Properties.BAN_HACKERS)
				{
					DBBannedAccount b = new DBBannedAccount();
					b.Author = "SERVER";
					b.Ip = client.TcpEndpointAddress;
					b.Account = client.Account.Name;
					b.DateBan = DateTime.Now;
					b.Type = "B";
					b.Reason = String.Format("Autoban wrong Account '{0}'", GameServer.Database.Escape(accountName));
					GameServer.Database.AddObject(b);
					GameServer.Database.SaveObject(b);
					GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account);
				}

				client.Disconnect();
				return;
			}

			if (client.Version >= GameClient.eClientVersion.Version1104)
			{
				packet.ReadIntLowEndian(); //unk - probably indicates customize or create
			}

			int charsCount = client.Version < GameClient.eClientVersion.Version173 ? 8 : 10;
			for (int i = 0; i < charsCount; i++)
			{
				string charName = packet.ReadString(24);

				//log.DebugFormat("Character[{0}] = {1}", i, charName);

				if (charName.Length == 0)
				{
					// 1.104+  if character is not in list but is in DB then delete the character
					if (client.Version >= GameClient.eClientVersion.Version1104)
					{
						CheckForDeletedCharacter(accountName, client, i);
					}

					//If the charname is empty, skip the other bytes
					packet.Skip(160);
					if (client.Version >= GameClient.eClientVersion.Version199)
					{
						// skip 4 bytes added in 1.99
						packet.Skip(4);
					}
				}
				else
				{
					// Graveen: changed the following to allow GMs to have special chars in their names (_,-, etc..)
					Regex nameCheck = new Regex("^[A-Z][a-zA-Z]");
					if (charName.Length < 3 || !nameCheck.IsMatch(charName))
					{
						if (client.Account.PrivLevel == 1)
						{
							if (ServerProperties.Properties.BAN_HACKERS)
							{
								DBBannedAccount b = new DBBannedAccount();
								b.Author = "SERVER";
								b.Ip = client.TcpEndpointAddress;
								b.Account = client.Account.Name;
								b.DateBan = DateTime.Now;
								b.Type = "B";
								b.Reason = String.Format("Autoban bad CharName '{0}'", GameServer.Database.Escape(charName));
								GameServer.Database.AddObject(b);
								GameServer.Database.SaveObject(b);
								GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account);
							}

							client.Disconnect();
							return;
						}
					}

					String select = String.Format("Name = '{0}'", GameServer.Database.Escape(charName));
					DOLCharacters character = GameServer.Database.SelectObject<DOLCharacters>(select);
					if (character != null)
					{
						if (character.AccountName != client.Account.Name)
						{
							if (Properties.BAN_HACKERS == true)
							{
								DBBannedAccount b = new DBBannedAccount();
								b.Author = "SERVER";
								b.Ip = client.TcpEndpointAddress;
								b.Account = client.Account.Name;
								b.DateBan = DateTime.Now;
								b.Type = "B";
								b.Reason = String.Format("Autoban CharName '{0}' on wrong Account '{1}'", GameServer.Database.Escape(charName), GameServer.Database.Escape(client.Account.Name));
								GameServer.Database.AddObject(b);
								GameServer.Database.SaveObject(b);
								GameServer.Instance.LogCheatAction(string.Format(b.Reason + ". Client Account: {0}, DB Account: {1}", client.Account.Name, character.AccountName));
							}

							client.Disconnect();
							return;
						}

						byte customizationMode = (byte)packet.ReadByte();

						// log.DebugFormat("CustomizationMode = {0} for charName {1}", customizationMode, charName);

						// check for update to existing character
						CheckCharacterForUpdates(client, packet, character, charName, customizationMode);
					}
					else
					{
						// create new character and return
						CreateCharacter(client, packet, charName, i);
					}
				}
			}
		}