feat: add outgoing messages to client

This commit is contained in:
k0t9i
2023-02-09 22:45:08 +04:00
parent abcf3b20c0
commit ad5d7a5159
25 changed files with 739 additions and 74 deletions

View File

@@ -12,12 +12,12 @@ namespace Client.Domain.Common
{
public static float Distance(this CreatureInterface creature, CreatureInterface other)
{
return creature.Transform.Position.HorizontalDistance(other.Transform.Position) / 100;
return creature.Transform.Position.HorizontalDistance(other.Transform.Position);
}
public static float DeltaZ(this CreatureInterface creature, CreatureInterface other)
{
return (creature.Transform.Position.Z - other.Transform.Position.Z) / 100;
return (creature.Transform.Position.Z - other.Transform.Position.Z);
}
}
}

View File

@@ -0,0 +1,28 @@
using Client.Domain.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.DTO
{
public class OutgoingMessage<T>
{
public readonly OutgoingMessageTypeEnum Type;
public readonly T? Content;
public OutgoingMessage(OutgoingMessageTypeEnum type, T? content = default)
{
Type = type;
Content = content;
}
}
public class EmptyOutgoingMessage : OutgoingMessage<uint>
{
public EmptyOutgoingMessage(OutgoingMessageTypeEnum type) : base(type)
{
}
}
}

View File

@@ -18,6 +18,6 @@ namespace Client.Domain.Entities
string BriefInfo { get; }
CreatureTypeEnum Type { get; }
uint AggroRadius { get; set; }
bool IsHostile { get; set; }
}
}

View File

@@ -62,6 +62,7 @@ namespace Client.Domain.Entities
}
}
public uint AggroRadius { get; set; } = 0;
public bool IsHostile { get; set; } = false;
public Hero(uint id, Transform transform, FullName fullName, VitalStats vitalStats, Phenotype phenotype, ExperienceInfo experienceInfo, PermanentStats permanentStats, VariableStats variableStats, Reputation reputation, InventoryInfo inventoryInfo, uint targetId, bool isStanding)
{

View File

@@ -74,7 +74,7 @@ namespace Client.Domain.Entities
{
string result = FullName.Nickname;
if (IsDead())
if (VitalStats.IsDead)
{
result += " (dead)";
}
@@ -124,17 +124,12 @@ namespace Client.Domain.Entities
private void VitalStats_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == "Hp" || e.PropertyName == "MaxHp")
if (e.PropertyName == "IsDead")
{
OnPropertyChanged("Name");
}
}
public bool IsDead()
{
return VitalStats.MaxHp > 0 && VitalStats.Hp <= 0;
}
private uint level;
private uint aggroRadius;
private VitalStats vitalStats;

View File

@@ -62,6 +62,7 @@ namespace Client.Domain.Entities
public VitalStats VitalStats { get => vitalStats; set => vitalStats = value; }
public CreatureTypeEnum Type { get => CreatureTypeEnum.Player; }
public uint AggroRadius { get; set; } = 0;
public bool IsHostile { get; set; } = false;
public Player(uint id, Transform transform, FullName fullName, Phenotype phenotype)
{

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Enums
{
public enum OutgoingMessageTypeEnum
{
Invalidate,
Move,
AcquireTarget,
Attack,
Pickup,
UseSkill,
UseItem,
ToggleSoulshot,
Sit,
Stand
}
}

View File

@@ -0,0 +1,14 @@
using Client.Domain.DTO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Parsers
{
public interface OutgoingMessageBuilderInterface
{
string Build<T>(OutgoingMessage<T> message);
}
}

View File

@@ -0,0 +1,289 @@
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;
namespace Client.Domain.Service
{
public class WorldHandler :
EventHandlerInterface<HeroCreatedEvent>,
EventHandlerInterface<HeroDeletedEvent>,
EventHandlerInterface<CreatureCreatedEvent>,
EventHandlerInterface<CreatureDeletedEvent>,
EventHandlerInterface<DropCreatedEvent>,
EventHandlerInterface<DropDeletedEvent>,
EventHandlerInterface<SkillCreatedEvent>,
EventHandlerInterface<SkillDeletedEvent>,
EventHandlerInterface<ItemCreatedEvent>,
EventHandlerInterface<ItemDeletedEvent>
{
public void RequestMoveToLocation(Vector3 location)
{
if (hero == null)
{
return;
}
SendMessage(OutgoingMessageTypeEnum.Move, location);
}
public void RequestMoveToEntity(uint id)
{
if (hero == null)
{
return;
}
if (!creatures.ContainsKey(id) && !drops.ContainsKey(id))
{
Debug.WriteLine("RequestMoveToEntity: entity " + id + " not found");
return;
}
var position = creatures.ContainsKey(id) ? creatures[id].Transform.Position : drops[id].Transform.Position;
RequestMoveToLocation(position);
}
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;
}
SendMessage(OutgoingMessageTypeEnum.UseSkill, id);
}
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);
}
private void SendMessage<T>(OutgoingMessageTypeEnum type, T? content = default)
{
var message = outgoingMessageBuilder.Build(
new OutgoingMessage<T>(type, content)
);
transport.SendAsync(message);
Debug.WriteLine(message);
}
private void SendMessage(OutgoingMessageTypeEnum type)
{
SendMessage<uint>(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 BaseItem? value);
}
#endregion
public WorldHandler(OutgoingMessageBuilderInterface outgoingMessageBuilder, TransportInterface transport)
{
this.outgoingMessageBuilder = outgoingMessageBuilder;
this.transport = transport;
}
private Hero? hero;
private ConcurrentDictionary<uint, CreatureInterface> creatures = new ConcurrentDictionary<uint, CreatureInterface>();
private ConcurrentDictionary<uint, Drop> drops = new ConcurrentDictionary<uint, Drop>();
private ConcurrentDictionary<uint, Skill> skills = new ConcurrentDictionary<uint, Skill>();
private ConcurrentDictionary<uint, BaseItem> items = new ConcurrentDictionary<uint, BaseItem>();
private readonly OutgoingMessageBuilderInterface outgoingMessageBuilder;
private readonly TransportInterface transport;
}
}

View File

@@ -12,12 +12,12 @@ namespace Client.Domain.ValueObjects
private uint cp;
private uint maxCp;
public uint Hp { get => hp; set { if (value != hp) { hp = value; OnPropertyChanged("Hp"); OnPropertyChanged("MaxHp"); } } }
public uint MaxHp { get => Math.Max(hp, maxHp); set { if (value != maxHp) { maxHp = value; OnPropertyChanged("MaxHp"); } } }
public uint Mp { get => mp; set { if (value != mp) { mp = value; OnPropertyChanged("Mp"); } } }
public uint MaxMp { get => maxMp; set { if (value != maxMp) { maxMp = value; OnPropertyChanged("MaxMp"); } } }
public uint Cp { get => cp; set { if (value != cp) { cp = value; OnPropertyChanged("Cp"); } } }
public uint MaxCp { get => maxCp; set { if (value != maxCp) { maxCp = value; OnPropertyChanged("MaxCp"); } } }
public uint Hp { get => hp; set { if (value != hp) { hp = value; OnPropertyChanged(); OnPropertyChanged("MaxHp"); OnPropertyChanged("IsDead"); } } }
public uint MaxHp { get => Math.Max(hp, maxHp); set { if (value != maxHp) { maxHp = value; OnPropertyChanged(); OnPropertyChanged("IsDead"); } } }
public uint Mp { get => mp; set { if (value != mp) { mp = value; OnPropertyChanged(); } } }
public uint MaxMp { get => maxMp; set { if (value != maxMp) { maxMp = value; OnPropertyChanged(); } } }
public uint Cp { get => cp; set { if (value != cp) { cp = value; OnPropertyChanged(); } } }
public uint MaxCp { get => maxCp; set { if (value != maxCp) { maxCp = value; OnPropertyChanged(); } } }
public double HpPercent
{
@@ -41,6 +41,8 @@ namespace Client.Domain.ValueObjects
}
}
public bool IsDead => MaxHp > 0 && hp == 0;
public VitalStats(uint hp, uint maxHp, uint mp, uint maxMp, uint cp, uint maxCp)
{
this.hp = hp;