/// <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); } } } }