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); } }
/// <summary> /// Check if a Character Needs update based to packet data /// </summary> /// <param name="pdata">packet data</param> /// <param name="client">client</param> /// <param name="character">db character</param> /// <returns>True if character need refreshment false if no refresh needed.</returns> private bool CheckCharacterForUpdates(CreationCharacterData pdata, GameClient client, DOLCharacters character) { int newModel = character.CurrentModel; if (pdata.CustomMode == 1 || pdata.CustomMode == 2 || pdata.CustomMode == 3) { bool flagChangedStats = false; if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION) { character.EyeSize = (byte)pdata.EyeSize; character.LipSize = (byte)pdata.LipSize; character.EyeColor = (byte)pdata.EyeColor; character.HairColor = (byte)pdata.HairColor; character.FaceType = (byte)pdata.FaceType; character.HairStyle = (byte)pdata.HairStyle; character.MoodType = (byte)pdata.MoodType; } if (pdata.CustomMode != 3 && client.Version >= GameClient.eClientVersion.Version189) { var stats = new Dictionary <eStat, int>(); stats[eStat.STR] = pdata.Strength; // Strength stats[eStat.DEX] = pdata.Dexterity; // Dexterity stats[eStat.CON] = pdata.NewConstitution; // New Constitution stats[eStat.QUI] = pdata.Quickness; // Quickness stats[eStat.INT] = pdata.Intelligence; // Intelligence stats[eStat.PIE] = pdata.Piety; // Piety stats[eStat.EMP] = pdata.Empathy; // Empathy stats[eStat.CHR] = pdata.Charisma; // Charisma // check for changed stats. flagChangedStats |= stats[eStat.STR] != character.Strength; flagChangedStats |= stats[eStat.CON] != character.Constitution; flagChangedStats |= stats[eStat.DEX] != character.Dexterity; flagChangedStats |= stats[eStat.QUI] != character.Quickness; flagChangedStats |= stats[eStat.INT] != character.Intelligence; flagChangedStats |= stats[eStat.PIE] != character.Piety; flagChangedStats |= stats[eStat.EMP] != character.Empathy; flagChangedStats |= stats[eStat.CHR] != character.Charisma; if (flagChangedStats) { ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class); if (charClass != null) { int points; bool valid = IsCustomPointsDistributionValid(character, stats, out points); // Hacking attemp ? if (points > MAX_STARTING_BONUS_POINTS) { if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (ServerProperties.Properties.BAN_HACKERS) { client.BanAccount(string.Format("Autoban Hack char update : Wrong allowed points:{0}", points)); } client.Disconnect(); return(false); } } // Error in setting points if (!valid) { return(true); } if (Properties.ALLOW_CUSTOMIZE_STATS_AFTER_CREATION) { // Set Stats, valid is ok. character.Strength = stats[eStat.STR]; character.Constitution = stats[eStat.CON]; character.Dexterity = stats[eStat.DEX]; character.Quickness = stats[eStat.QUI]; character.Intelligence = stats[eStat.INT]; character.Piety = stats[eStat.PIE]; character.Empathy = stats[eStat.EMP]; character.Charisma = stats[eStat.CHR]; if (log.IsInfoEnabled) { log.InfoFormat("Character {0} Stats updated in cache!", character.Name); } if (client.Player != null) { foreach (var stat in stats.Keys) { client.Player.ChangeBaseStat(stat, (short)(stats[stat] - client.Player.GetBaseStat(stat))); } if (log.IsInfoEnabled) { log.InfoFormat("Character {0} Player Stats updated in cache!", character.Name); } } } } else if (log.IsErrorEnabled) { log.ErrorFormat("No CharacterClass with ID {0} found", character.Class); } } } if (pdata.CustomMode == 2) // change player customization { if (client.Account.PrivLevel == 1 && ((pdata.CreationModel >> 11) & 3) == 0) { if (ServerProperties.Properties.BAN_HACKERS) // Player size must be > 0 (from 1 to 3) { client.BanAccount(string.Format("Autoban Hack char update : zero character size in model:{0}", newModel)); client.Disconnect(); return(false); } return(true); } character.CustomisationStep = 2; // disable config button if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION) { if (pdata.CreationModel != character.CreationModel) { character.CurrentModel = newModel; } if (log.IsInfoEnabled) { log.InfoFormat("Character {0} face properties configured by account {1}!", character.Name, client.Account.Name); } } } else if (pdata.CustomMode == 3) //auto config -- seems someone thinks this is not possible? { character.CustomisationStep = 3; // enable config button to player } //Save the character in the database GameServer.Database.SaveObject(character); } return(false); }
private bool CreateCharacter(CreationCharacterData pdata, GameClient client, int accountSlot) { Account account = client.Account; var ch = new DOLCharacters(); ch.AccountName = account.Name; ch.Name = pdata.CharName; if (pdata.CustomMode == 0x01) { ch.EyeSize = (byte)pdata.EyeSize; ch.LipSize = (byte)pdata.LipSize; ch.EyeColor = (byte)pdata.EyeColor; ch.HairColor = (byte)pdata.HairColor; ch.FaceType = (byte)pdata.FaceType; ch.HairStyle = (byte)pdata.HairStyle; ch.MoodType = (byte)pdata.MoodType; ch.CustomisationStep = 2; // disable config button if (log.IsDebugEnabled) { log.Debug("Disable Config Button"); } } ch.Level = 1; // Set Realm and Class ch.Realm = pdata.Realm; ch.Class = pdata.Class; // Set Account Slot, Gender ch.AccountSlot = accountSlot + ch.Realm * 100; ch.Gender = pdata.Gender; // Set Race ch.Race = pdata.Race; ch.CreationModel = pdata.CreationModel; ch.CurrentModel = ch.CreationModel; ch.Region = pdata.Region; ch.Strength = pdata.Strength; ch.Dexterity = pdata.Dexterity; ch.Constitution = pdata.Constitution; ch.Quickness = pdata.Quickness; ch.Intelligence = pdata.Intelligence; ch.Piety = pdata.Piety; ch.Empathy = pdata.Empathy; ch.Charisma = pdata.Charisma; // defaults ch.CreationDate = DateTime.Now; ch.Endurance = 100; ch.MaxEndurance = 100; ch.Concentration = 100; ch.MaxSpeed = GamePlayer.PLAYER_BASE_SPEED; if (log.IsDebugEnabled) { log.DebugFormat("Creation {0} character, class:{1}, realm:{2}", client.Version, ch.Class, ch.Realm); } // Is class disabled ? int occurences = 0; List <string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true); occurences = (from j in disabled_classes where j == ch.Class.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (log.IsDebugEnabled) { log.DebugFormat("Client {0} tried to create a disabled classe: {1}", client.Account.Name, (eCharacterClass)ch.Class); } return(true); } // check if race disabled List <string> disabled_races = Properties.DISABLED_RACES.SplitCSV(true); occurences = (from j in disabled_races where j == ch.Race.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (log.IsDebugEnabled) { log.DebugFormat("Client {0} tried to create a disabled race: {1}", client.Account.Name, (eRace)ch.Race); } return(true); } // If sending invalid Class ID if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class)) { if (log.IsErrorEnabled) { log.ErrorFormat("{0} tried to create a character with wrong class ID: {1}, realm:{2}", client.Account.Name, ch.Class, ch.Realm); } if (ServerProperties.Properties.BAN_HACKERS) { client.BanAccount(string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name)); client.Disconnect(); return(false); } return(true); } // check if client tried to create invalid char if (!IsCharacterValid(ch)) { if (log.IsWarnEnabled) { log.WarnFormat("{0} tried to create invalid character:\nchar name={1}, gender={2}, race={3}, realm={4}, class={5}, region={6}" + "\nstr={7}, con={8}, dex={9}, qui={10}, int={11}, pie={12}, emp={13}, chr={14}", ch.AccountName, ch.Name, ch.Gender, ch.Race, ch.Realm, ch.Class, ch.Region, ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma); } return(true); } //Save the character in the database GameServer.Database.AddObject(ch); // Fire the character creation event // This is Where Most Creation Script should take over to update any data they would like ! GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client)); //write changes GameServer.Database.SaveObject(ch); // Log creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", pdata.CharName); client.Account.Characters = null; if (log.IsInfoEnabled) { log.InfoFormat("Character {0} created on Account {1}!", pdata.CharName, account); } // Reload Account Relations GameServer.Database.FillObjectRelations(client.Account); return(true); }
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); } }
/// <summary> /// Check if a Character Needs update based to packet data /// </summary> /// <param name="pdata">packet data</param> /// <param name="client">client</param> /// <param name="character">db character</param> /// <returns>True if character need refreshment false if no refresh needed.</returns> private bool CheckCharacterForUpdates(CreationCharacterData pdata, GameClient client, DOLCharacters character) { int newModel = character.CurrentModel; if (pdata.CustomMode == 1 || pdata.CustomMode == 2 || pdata.CustomMode == 3) { bool flagChangedStats = false; if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION) { character.EyeSize = (byte)pdata.EyeSize; character.LipSize = (byte)pdata.LipSize; character.EyeColor = (byte)pdata.EyeColor; character.HairColor = (byte)pdata.HairColor; character.FaceType = (byte)pdata.FaceType; character.HairStyle = (byte)pdata.HairStyle; character.MoodType = (byte)pdata.MoodType; } if (pdata.CustomMode != 3 && client.Version >= GameClient.eClientVersion.Version189) { var stats = new Dictionary<eStat, int>(); stats[eStat.STR] = pdata.Strength; // Strength stats[eStat.DEX] = pdata.Dexterity; // Dexterity stats[eStat.CON] = pdata.NewConstitution; // New Constitution stats[eStat.QUI] = pdata.Quickness; // Quickness stats[eStat.INT] = pdata.Intelligence; // Intelligence stats[eStat.PIE] = pdata.Piety; // Piety stats[eStat.EMP] = pdata.Empathy; // Empathy stats[eStat.CHR] = pdata.Charisma; // Charisma // check for changed stats. flagChangedStats |= stats[eStat.STR] != character.Strength; flagChangedStats |= stats[eStat.CON] != character.Constitution; flagChangedStats |= stats[eStat.DEX] != character.Dexterity; flagChangedStats |= stats[eStat.QUI] != character.Quickness; flagChangedStats |= stats[eStat.INT] != character.Intelligence; flagChangedStats |= stats[eStat.PIE] != character.Piety; flagChangedStats |= stats[eStat.EMP] != character.Empathy; flagChangedStats |= stats[eStat.CHR] != character.Charisma; if (flagChangedStats) { ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class); if (charClass != null) { int points; bool valid = IsCustomPointsDistributionValid(character, stats, out points); // Hacking attemp ? if (points > MAX_STARTING_BONUS_POINTS) { if ((ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (ServerProperties.Properties.BAN_HACKERS) client.BanAccount(string.Format("Autoban Hack char update : Wrong allowed points:{0}", points)); client.Disconnect(); return false; } } // Error in setting points if (!valid) { return true; } if (Properties.ALLOW_CUSTOMIZE_STATS_AFTER_CREATION) { // Set Stats, valid is ok. character.Strength = stats[eStat.STR]; character.Constitution = stats[eStat.CON]; character.Dexterity = stats[eStat.DEX]; character.Quickness = stats[eStat.QUI]; character.Intelligence = stats[eStat.INT]; character.Piety = stats[eStat.PIE]; character.Empathy = stats[eStat.EMP]; character.Charisma = stats[eStat.CHR]; if (log.IsInfoEnabled) log.InfoFormat("Character {0} Stats updated in cache!", character.Name); if (client.Player != null) { foreach(var stat in stats.Keys) client.Player.ChangeBaseStat(stat, (short)(stats[stat] - client.Player.GetBaseStat(stat))); if (log.IsInfoEnabled) log.InfoFormat("Character {0} Player Stats updated in cache!", character.Name); } } } else if (log.IsErrorEnabled) log.ErrorFormat("No CharacterClass with ID {0} found", character.Class); } } if (pdata.CustomMode == 2) // change player customization { if (client.Account.PrivLevel == 1 && ((pdata.CreationModel >> 11) & 3) == 0) { if (ServerProperties.Properties.BAN_HACKERS) // Player size must be > 0 (from 1 to 3) { client.BanAccount(string.Format("Autoban Hack char update : zero character size in model:{0}", newModel)); client.Disconnect(); return false; } return true; } character.CustomisationStep = 2; // disable config button if (Properties.ALLOW_CUSTOMIZE_FACE_AFTER_CREATION) { if (pdata.CreationModel != character.CreationModel) character.CurrentModel = newModel; if (log.IsInfoEnabled) log.InfoFormat("Character {0} face properties configured by account {1}!", character.Name, client.Account.Name); } } else if (pdata.CustomMode == 3) //auto config -- seems someone thinks this is not possible? { character.CustomisationStep = 3; // enable config button to player } //Save the character in the database GameServer.Database.SaveObject(character); } return false; }
private bool CreateCharacter(CreationCharacterData pdata, GameClient client, int accountSlot) { Account account = client.Account; var ch = new DOLCharacters(); ch.AccountName = account.Name; ch.Name = pdata.CharName; if (pdata.CustomMode == 0x01) { ch.EyeSize = (byte)pdata.EyeSize; ch.LipSize = (byte)pdata.LipSize; ch.EyeColor = (byte)pdata.EyeColor; ch.HairColor = (byte)pdata.HairColor; ch.FaceType = (byte)pdata.FaceType; ch.HairStyle = (byte)pdata.HairStyle; ch.MoodType = (byte)pdata.MoodType; ch.CustomisationStep = 2; // disable config button if (log.IsDebugEnabled) log.Debug("Disable Config Button"); } ch.Level = 1; // Set Realm and Class ch.Realm = pdata.Realm; ch.Class = pdata.Class; // Set Account Slot, Gender ch.AccountSlot = accountSlot + ch.Realm * 100; ch.Gender = pdata.Gender; // Set Race ch.Race = pdata.Race; ch.CreationModel = pdata.CreationModel; ch.CurrentModel = ch.CreationModel; ch.Region = pdata.Region; ch.Strength = pdata.Strength; ch.Dexterity = pdata.Dexterity; ch.Constitution = pdata.Constitution; ch.Quickness = pdata.Quickness; ch.Intelligence = pdata.Intelligence; ch.Piety = pdata.Piety; ch.Empathy = pdata.Empathy; ch.Charisma = pdata.Charisma; // defaults ch.CreationDate = DateTime.Now; ch.Endurance = 100; ch.MaxEndurance = 100; ch.Concentration = 100; ch.MaxSpeed = GamePlayer.PLAYER_BASE_SPEED; if (log.IsDebugEnabled) log.DebugFormat("Creation {0} character, class:{1}, realm:{2}", client.Version, ch.Class, ch.Realm); // Is class disabled ? int occurences = 0; List<string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true); occurences = (from j in disabled_classes where j == ch.Class.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (log.IsDebugEnabled) log.DebugFormat("Client {0} tried to create a disabled classe: {1}", client.Account.Name, (eCharacterClass)ch.Class); return true; } // check if race disabled List<string> disabled_races = Properties.DISABLED_RACES.SplitCSV(true); occurences = (from j in disabled_races where j == ch.Race.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { if (log.IsDebugEnabled) log.DebugFormat("Client {0} tried to create a disabled race: {1}", client.Account.Name, (eRace)ch.Race); return true; } // If sending invalid Class ID if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class)) { if (log.IsErrorEnabled) log.ErrorFormat("{0} tried to create a character with wrong class ID: {1}, realm:{2}", client.Account.Name, ch.Class, ch.Realm); if (ServerProperties.Properties.BAN_HACKERS) { client.BanAccount(string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name)); client.Disconnect(); return false; } return true; } // check if client tried to create invalid char if (!IsCharacterValid(ch)) { if (log.IsWarnEnabled) { log.WarnFormat("{0} tried to create invalid character:\nchar name={1}, gender={2}, race={3}, realm={4}, class={5}, region={6}" + "\nstr={7}, con={8}, dex={9}, qui={10}, int={11}, pie={12}, emp={13}, chr={14}", ch.AccountName, ch.Name, ch.Gender, ch.Race, ch.Realm, ch.Class, ch.Region, ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma); } return true; } //Save the character in the database GameServer.Database.AddObject(ch); // Fire the character creation event // This is Where Most Creation Script should take over to update any data they would like ! GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client)); //write changes GameServer.Database.SaveObject(ch); // Log creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", pdata.CharName); client.Account.Characters = null; if (log.IsInfoEnabled) log.InfoFormat("Character {0} created on Account {1}!", pdata.CharName, account); // Reload Account Relations GameServer.Database.FillObjectRelations(client.Account); return true; }