using Microsoft.EntityFrameworkCore; using NetCoreServer; using Server.DB; using Server.DB.Documents; using Server.Services; using Wonderking.Game.Data.Character; using Wonderking.Game.Mapping; using Wonderking.Packets.Incoming; using Wonderking.Packets.Outgoing; using Wonderking.Packets.Outgoing.Data; namespace Server.PacketHandlers; public class CharacterCreationHandler : IPacketHandler { private readonly WonderkingContext _wonderkingContext; private readonly ItemObjectPoolService _itemObjectPoolService; private readonly CharacterStatsMappingConfiguration _characterStatsMapping; public CharacterCreationHandler(WonderkingContext wonderkingContext, ItemObjectPoolService itemObjectPoolService, CharacterStatsMappingConfiguration characterStatsMappingConfiguration) { _wonderkingContext = wonderkingContext; _itemObjectPoolService = itemObjectPoolService; _characterStatsMapping = characterStatsMappingConfiguration; } public async Task HandleAsync(CharacterCreationPacket packet, TcpSession session) { var authSession = session as AuthSession; var account = _wonderkingContext.Accounts.FirstOrDefault(a => authSession != null && a.Id == authSession.AccountId); var mappedDefaultItems = _characterStatsMapping.DefaultCharacterMapping.Items .Select(i => _itemObjectPoolService.GetBaseInventoryItem(i.Id, i.Quantity)).ToArray(); var firstJobConfig = packet.FirstJob switch { 1 => _characterStatsMapping.Swordsman, 2 => _characterStatsMapping.Mage, 3 => _characterStatsMapping.Thief, 4 => _characterStatsMapping.Scout, _ => _characterStatsMapping.Swordsman }; var mappedJobItems = firstJobConfig.Items .Select(i => _itemObjectPoolService.GetBaseInventoryItem(i.Id, i.Quantity)).ToArray(); InventoryItem[] items = [ .. mappedDefaultItems, .. mappedJobItems, _itemObjectPoolService.GetBaseInventoryItem((ushort)((packet.FirstJob - 1) * 6 + ((byte)packet.Gender - 1) * 3 + packet.Hair + 1)), _itemObjectPoolService.GetBaseInventoryItem((ushort)((packet.FirstJob - 1) * 6 + ((byte)packet.Gender - 1) * 3 + packet.Eyes + 25)), _itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 + packet.Shirt + 49)), _itemObjectPoolService.GetBaseInventoryItem((ushort)(((byte)packet.Gender - 1) * 3 + packet.Pants + 58)), ]; var calculateCurrentMana = CalculateCurrentMana(1, firstJobConfig); var calculateCurrentHealth = CalculateCurrentHealth(1, firstJobConfig); var toBeAddedCharacter = new Character { Account = account, MapId = 300, Name = packet.Name, LastXCoordinate = 113, LastYCoordinate = 0, PvPLevel = PvPLevel.None, Gender = packet.Gender, Experience = 0, Level = 1, InventoryItems = items, BaseStats = firstJobConfig.BaseStats, JobData = new JobData { FirstJob = packet.FirstJob, SecondJob = 0, ThirdJob = 0, FourthJob = 0 }, Health = calculateCurrentHealth, Mana = calculateCurrentMana }; account?.Characters.Add(toBeAddedCharacter); await _wonderkingContext.SaveChangesAsync().ConfigureAwait(true); var amountOfCharacters = await _wonderkingContext.Characters.AsNoTrackingWithIdentityResolution() .CountAsync(c => authSession != null && c.Account.Id == authSession.AccountId).ConfigureAwait(true); var character = await _wonderkingContext.Characters.AsNoTrackingWithIdentityResolution() .Where(c => authSession != null && c.Account.Id == authSession.AccountId && c.Name == packet.Name) .Select(c => new CharacterData { Name = c.Name, Job = c.JobData, Gender = c.Gender, Level = c.Level, Experience = 0, Stats = c.BaseStats, Health = c.Health, Mana = c.Mana, EquippedItems = c.InventoryItems.Where(item => item.InventoryTab == InventoryTab.WornEquipment) .Select(item => item.ItemId) .ToArray(), EquippedCashItems = c.InventoryItems .Where(item => item.InventoryTab == InventoryTab.WornCashEquipment) .Select(item => item.ItemId) .ToArray(), }).FirstAsync().ConfigureAwait(true); await authSession.SendAsync(new CharacterCreationResponsePacket { Character = character, Slot = amountOfCharacters - 1, isDuplicate = false, }).ConfigureAwait(false); } private static int CalculateCurrentHealth(ushort level, JobSpecificMapping firstJobConfig) { return (int)((level - 1) * firstJobConfig.DynamicStats.HealthPerLevel + firstJobConfig.BaseStats.Vitality * firstJobConfig.DynamicStats.HealthPerVitality); } private static int CalculateCurrentMana(ushort level, JobSpecificMapping firstJobConfig) { return (int)((level - 1) * firstJobConfig.DynamicStats.ManaPerLevel + firstJobConfig.BaseStats.Wisdom * firstJobConfig.DynamicStats.ManaPerWisdom); } }