using Client.Domain.Entities; using Client.Domain.Events; using Client.Domain.Parsers; using Client.Domain.ValueObjects; using Client.Domain.DTO; using Client.Domain.Enums; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Collections.Concurrent; using Client.Domain.Transports; using Client.Domain.Common; using Client.Domain.Helpers; namespace Client.Domain.Service { public class WorldHandler : EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface, EventHandlerInterface { public Hero? Hero => hero; public void RequestMoveToLocation(Vector3 location) { if (hero == null) { return; } SendMessage(OutgoingMessageTypeEnum.Move, location); } public void RequestAcquireTarget(uint id) { if (hero == null) { return; } if (hero.TargetId == id) { Debug.WriteLine("RequestAcquireTarget: creature " + id + " is already target"); return; } if (!creatures.ContainsKey(id) && hero.Id != id) { Debug.WriteLine("RequestAcquireTarget: creature " + id + " not found"); return; } SendMessage(OutgoingMessageTypeEnum.AcquireTarget, id); } public void RequestAttackOrFollow(uint id) { if (hero == null) { return; } if (!creatures.ContainsKey(id)) { Debug.WriteLine("RequestAttackOrFollow: creature " + id + " not found"); return; } SendMessage(OutgoingMessageTypeEnum.Attack, id); } public void RequestPickUp(uint id) { if (hero == null) { return; } if (!drops.ContainsKey(id)) { Debug.WriteLine("RequestPickUp: drop " + id + " not found"); return; } SendMessage(OutgoingMessageTypeEnum.Pickup, id); } public void RequestUseSkill(uint id, bool isForced, bool isShiftPressed) { if (hero == null) { return; } if (!skills.TryGetValue(id, out Skill? skill)) { Debug.WriteLine("RequestUseSkill: skill " + id + " not found"); return; } if (!skill.IsActive) { Debug.WriteLine("RequestUseSkill: skill " + id + " is passive"); return; } var data = new UseSkillParams { skillId = id, isForced = isForced, isShiftPressed = isShiftPressed }; SendMessage(OutgoingMessageTypeEnum.UseSkill, data); } public void RequestUseItem(uint id) { if (hero == null) { return; } if (!items.ContainsKey(id)) { Debug.WriteLine("RequestUseItem: item " + id + " not found"); return; } SendMessage(OutgoingMessageTypeEnum.UseItem, id); } public void RequestToggleAutouseSoulshot(uint id) { if (hero == null) { return; } if (!items.ContainsKey(id)) { Debug.WriteLine("RequestToggleAutouseSoulshot: item " + id + " not found"); return; } SendMessage(OutgoingMessageTypeEnum.ToggleSoulshot, id); } public void RequestSit() { if (hero == null) { return; } if (!hero.IsStanding) { Debug.WriteLine("RequestSit: hero is already sitting"); return; } SendMessage(OutgoingMessageTypeEnum.Sit); } public void RequestStand() { if (hero == null) { return; } if (hero.IsStanding) { Debug.WriteLine("RequestStand: hero is already standing"); return; } SendMessage(OutgoingMessageTypeEnum.Stand); } public void RequestRestartPoint(RestartPointTypeEnum type) { if (hero == null) { return; } SendMessage(OutgoingMessageTypeEnum.RestartPoint, type); } public List GetAliveMobsSortedByDistanceToHero(uint deltaZ) { if (hero == null) { return new List { }; } return creatures .Where(a => { return a.Value is NPC && a.Value.IsHostile && !a.Value.VitalStats.IsDead && MathF.Abs(a.Value.DeltaZ(hero)) <= deltaZ; }) .OrderBy(a => a.Value.Distance(hero)) .Select(a => (NPC)a.Value) .ToList(); } public List GetDeadMobsSortedByDistanceToHero(uint deltaZ) { if (hero == null) { return new List { }; } return creatures .Where(a => { return a.Value is NPC && a.Value.IsHostile && a.Value.VitalStats.IsDead && MathF.Abs(a.Value.DeltaZ(hero)) <= deltaZ; }) .OrderBy(a => a.Value.Distance(hero)) .Select(a => (NPC)a.Value) .ToList(); } public List GetDropsSortedByDistanceToHero(uint deltaZ) { if (hero == null) { return new List { }; } return drops .Where(x => MathF.Abs(x.Value.Transform.Position.Z - hero.Transform.Position.Z) <= deltaZ) .OrderBy(a => a.Value.Transform.Position.HorizontalDistance(hero.Transform.Position)) .Select(a => a.Value) .ToList(); } public Skill? GetSkillById(uint id) { return skills.GetValueOrDefault(id); } public ItemInterface? GetItemById(uint id) { return items.Select(x => x.Value) .Where(x => x.ItemId == id) .FirstOrDefault(); } public List GetShotItems() { var shotIds = itemInfoHelper.GetAllItems() .Where(x => x.IsShot) .Select(x => x.Id) .ToDictionary(x => x, x => x); return items.Select(x => x.Value) .Where(x => x is EtcItem && shotIds.ContainsKey(x.ItemId)) .Cast() .ToList(); } public List GetGuards() { if (hero == null) { return new List { }; } var npcIds = npcInfoHelper.GetAllNpc() .Where(x => x.IsGuard) .Select(x => x.Id) .ToDictionary(x => x, x => x); return creatures .Where(x => { return x.Value is NPC && npcIds.ContainsKey(((NPC)x.Value).NpcId); }) .Select(x => (NPC) x.Value) .OrderBy(x => x.Distance(hero)) .ToList(); } public WeaponItem? GetEquippedWeapon() { return items.Select(x => x.Value) .Where(x => { return x is WeaponItem && ((WeaponItem)x).IsEquipped; }) .Cast() .FirstOrDefault(); } private void SendMessage(OutgoingMessageTypeEnum type, T? content = default) { var message = outgoingMessageBuilder.Build( new OutgoingMessage(type, content) ); transport.SendAsync(message); } private void SendMessage(OutgoingMessageTypeEnum type) { SendMessage(type); } #region Handle Entity public void Handle(HeroCreatedEvent @event) { hero = @event.Hero; } public void Handle(HeroDeletedEvent @event) { hero = null; } public void Handle(CreatureCreatedEvent @event) { if (!creatures.ContainsKey(@event.Creature.Id)) { creatures.TryAdd(@event.Creature.Id, @event.Creature); } } public void Handle(CreatureDeletedEvent @event) { creatures.Remove(@event.Id, out CreatureInterface? value); } public void Handle(DropCreatedEvent @event) { if (!drops.ContainsKey(@event.Drop.Id)) { drops.TryAdd(@event.Drop.Id, @event.Drop); } } public void Handle(DropDeletedEvent @event) { drops.Remove(@event.Id, out Drop? value); } public void Handle(SkillCreatedEvent @event) { if (!skills.ContainsKey(@event.Skill.Id)) { skills.TryAdd(@event.Skill.Id, @event.Skill); } } public void Handle(SkillDeletedEvent @event) { skills.Remove(@event.Id, out Skill? value); } public void Handle(ItemCreatedEvent @event) { if (!items.ContainsKey(@event.Item.Id)) { items.TryAdd(@event.Item.Id, @event.Item); } } public void Handle(ItemDeletedEvent @event) { items.Remove(@event.Id, out ItemInterface? value); } #endregion public WorldHandler(OutgoingMessageBuilderInterface outgoingMessageBuilder, TransportInterface transport, ItemInfoHelperInterface itemInfoHelper, NpcInfoHelperInterface npcInfoHelper) { this.outgoingMessageBuilder = outgoingMessageBuilder; this.transport = transport; this.itemInfoHelper = itemInfoHelper; this.npcInfoHelper = npcInfoHelper; } private Hero? hero; private ConcurrentDictionary creatures = new ConcurrentDictionary(); private ConcurrentDictionary drops = new ConcurrentDictionary(); private ConcurrentDictionary skills = new ConcurrentDictionary(); private ConcurrentDictionary items = new ConcurrentDictionary(); private readonly OutgoingMessageBuilderInterface outgoingMessageBuilder; private readonly TransportInterface transport; private ItemInfoHelperInterface itemInfoHelper; private readonly NpcInfoHelperInterface npcInfoHelper; } }