feat: add event bus

This commit is contained in:
k0t9i 2023-01-31 14:45:40 +04:00
parent ea6778a3bd
commit b8b92b7cf8
14 changed files with 240 additions and 48 deletions

View File

@ -17,6 +17,9 @@ using Client.Domain.ViewModels;
using Client.Application.ViewModels; using Client.Application.ViewModels;
using Client.Domain.Helpers; using Client.Domain.Helpers;
using Client.Infrastructure.Helpers; using Client.Infrastructure.Helpers;
using Client.Domain.Events;
using Client.Infrastructure.Events;
using System;
namespace Client namespace Client
{ {
@ -70,9 +73,7 @@ namespace Client
.AddSingleton( .AddSingleton(
typeof(Bot), typeof(Bot),
x => new Bot( x => new Bot(
x.GetRequiredService<TransportInterface>(), x.GetRequiredService<IServiceProvider>(),
x.GetRequiredService<MessageParserInterface>(),
x.GetRequiredService<EntityHandlerFactoryInterface>(),
config.GetValue<string>("DLLName") ?? "" config.GetValue<string>("DLLName") ?? ""
) )
) )
@ -86,6 +87,7 @@ namespace Client
) )
.AddSingleton(typeof(ExperienceHelperInterface), typeof(ConfigurationExperienceHelper)) .AddSingleton(typeof(ExperienceHelperInterface), typeof(ConfigurationExperienceHelper))
.AddSingleton(typeof(NpcInfoHelperInterface), typeof(ConfigurationNpcInfoHelper)) .AddSingleton(typeof(NpcInfoHelperInterface), typeof(ConfigurationNpcInfoHelper))
.AddSingleton(typeof(EventBusInterface), typeof(InMemoryEventBus))
.AddTransient(typeof(EntityFactoryInterface<Hero>), typeof(EntityFactory<Hero>)) .AddTransient(typeof(EntityFactoryInterface<Hero>), typeof(EntityFactory<Hero>))
.AddTransient(typeof(EntityFactoryInterface<Drop>), typeof(EntityFactory<Drop>)) .AddTransient(typeof(EntityFactoryInterface<Drop>), typeof(EntityFactory<Drop>))

View File

@ -1,6 +1,7 @@
using Client.Application.Extensions; using Client.Application.Extensions;
using Client.Domain.Common; using Client.Domain.Common;
using Client.Domain.Entities; using Client.Domain.Entities;
using Client.Domain.Events;
using Client.Domain.ValueObjects; using Client.Domain.ValueObjects;
using Client.Domain.ViewModels; using Client.Domain.ViewModels;
using System; using System;
@ -17,7 +18,13 @@ using System.Windows.Media;
namespace Client.Application.ViewModels namespace Client.Application.ViewModels
{ {
public class MainViewModel : NotifyPropertyChanged, MainViewModelInterface public class MainViewModel :
NotifyPropertyChanged,
MainViewModelInterface,
EventHandlerInterface<HeroCreatedEvent>,
EventHandlerInterface<HeroDeletedEvent>,
EventHandlerInterface<NpcCreatedEvent>,
EventHandlerInterface<NpcDeletedEvent>
{ {
public void AddChatMessage(ChatMessage chatMessage) public void AddChatMessage(ChatMessage chatMessage)
@ -25,32 +32,6 @@ namespace Client.Application.ViewModels
ChatMessages.Add(new ChatMessageViewModel(chatMessage)); ChatMessages.Add(new ChatMessageViewModel(chatMessage));
} }
public void CreateHero(Hero hero)
{
Hero = new HeroSummaryInfoViewModel(hero);
this.hero = hero;
OnPropertyChanged("Hero");
}
public void DeleteHero()
{
Hero = null;
hero = null;
OnPropertyChanged("Hero");
}
public void AddNpc(NPC npc)
{
if (hero != null)
{
Creatures.Add(new NpcListViewModel(npc, hero));
}
}
public void RemoveNpc(NPC npc)
{
Creatures.RemoveAll(x => x.Id == npc.Id);
}
public void AddPlayer(Player player) public void AddPlayer(Player player)
{ {
if (hero != null) if (hero != null)
@ -77,6 +58,33 @@ namespace Client.Application.ViewModels
Drops.RemoveAll(x => x.Id == drop.Id); Drops.RemoveAll(x => x.Id == drop.Id);
} }
public void Handle(HeroCreatedEvent @event)
{
Hero = new HeroSummaryInfoViewModel(@event.Hero);
hero = @event.Hero;
OnPropertyChanged("Hero");
}
public void Handle(HeroDeletedEvent @event)
{
Hero = null;
hero = null;
OnPropertyChanged("Hero");
}
public void Handle(NpcCreatedEvent @event)
{
if (hero != null)
{
Creatures.Add(new NpcListViewModel(@event.NPC, hero));
}
}
public void Handle(NpcDeletedEvent @event)
{
Creatures.RemoveAll(x => x.Id == @event.Id);
}
public ObservableCollection<ChatMessageViewModel> ChatMessages { get; } = new ObservableCollection<ChatMessageViewModel>(); public ObservableCollection<ChatMessageViewModel> ChatMessages { get; } = new ObservableCollection<ChatMessageViewModel>();
public ObservableCollection<CreatureListViewModelInterface> Creatures { get; } = new ObservableCollection<CreatureListViewModelInterface>(); public ObservableCollection<CreatureListViewModelInterface> Creatures { get; } = new ObservableCollection<CreatureListViewModelInterface>();
public ObservableCollection<DropListViewModel> Drops { get; } = new ObservableCollection<DropListViewModel>(); public ObservableCollection<DropListViewModel> Drops { get; } = new ObservableCollection<DropListViewModel>();

View File

@ -5,9 +5,12 @@ using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Client.Domain.Events;
using Client.Domain.Factories; using Client.Domain.Factories;
using Client.Domain.Parsers; using Client.Domain.Parsers;
using Client.Domain.Transports; using Client.Domain.Transports;
using Client.Domain.ViewModels;
using Microsoft.Extensions.DependencyInjection;
namespace Client namespace Client
{ {
@ -19,13 +22,20 @@ namespace Client
private readonly TransportInterface transport; private readonly TransportInterface transport;
private readonly MessageParserInterface messageParser; private readonly MessageParserInterface messageParser;
private readonly EntityHandlerFactoryInterface entityHandlerFactory; private readonly EntityHandlerFactoryInterface entityHandlerFactory;
private readonly EventBusInterface eventBus;
private readonly IServiceProvider serviceProvider;
private readonly string dllName; private readonly string dllName;
public Bot(TransportInterface transport, MessageParserInterface messageParser, EntityHandlerFactoryInterface entityHandlerFactory, string dllName) public Bot(
IServiceProvider serviceProvider,
string dllName
)
{ {
this.transport = transport; transport = serviceProvider.GetRequiredService<TransportInterface>();
this.messageParser = messageParser; messageParser = serviceProvider.GetRequiredService<MessageParserInterface>();
this.entityHandlerFactory = entityHandlerFactory; entityHandlerFactory = serviceProvider.GetRequiredService<EntityHandlerFactoryInterface>();
eventBus = serviceProvider.GetRequiredService<EventBusInterface>();
this.serviceProvider = serviceProvider;
this.dllName = dllName; this.dllName = dllName;
} }
@ -41,6 +51,8 @@ namespace Client
Debug.WriteLine(dllName + " loaded\n"); Debug.WriteLine(dllName + " loaded\n");
transport.Message += OnMessage; transport.Message += OnMessage;
SubscribeAllHandlers();
await transport.ConnectAsync(); await transport.ConnectAsync();
await transport.SendAsync("invalidate"); await transport.SendAsync("invalidate");
while (true) while (true)
@ -50,6 +62,15 @@ namespace Client
} }
} }
private void SubscribeAllHandlers()
{
var viewModel = serviceProvider.GetRequiredService<MainViewModelInterface>();
eventBus.Subscrbe((EventHandlerInterface<HeroCreatedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<HeroDeletedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<NpcCreatedEvent>)viewModel);
eventBus.Subscrbe((EventHandlerInterface<NpcDeletedEvent>)viewModel);
}
private void OnMessage(string args) private void OnMessage(string args)
{ {
try try

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public interface EventBusInterface
{
void Subscrbe<T>(EventHandlerInterface<T> handler) where T : EventInterface;
void Unsubscrbe<T>(EventHandlerInterface<T> handler) where T : EventInterface;
void Publish<T>(T @event) where T : EventInterface;
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public interface EventHandlerInterface
{
}
public interface EventHandlerInterface<T> : EventHandlerInterface where T : EventInterface
{
void Handle(T @event);
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public interface EventInterface
{
}
}

View File

@ -0,0 +1,19 @@
using Client.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public class HeroCreatedEvent : EventInterface
{
public readonly Hero Hero;
public HeroCreatedEvent(Hero hero)
{
Hero = hero;
}
}
}

View File

@ -0,0 +1,13 @@
using Client.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public class HeroDeletedEvent : EventInterface
{
}
}

View File

@ -0,0 +1,19 @@
using Client.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public class NpcCreatedEvent : EventInterface
{
public readonly NPC NPC;
public NpcCreatedEvent(NPC npc)
{
NPC = npc;
}
}
}

View File

@ -0,0 +1,19 @@
using Client.Domain.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Client.Domain.Events
{
public class NpcDeletedEvent : EventInterface
{
public readonly uint Id;
public NpcDeletedEvent(uint id)
{
Id = id;
}
}
}

View File

@ -1,4 +1,5 @@
using Client.Domain.Entities; using Client.Domain.Entities;
using Client.Domain.Events;
using Client.Domain.Factories; using Client.Domain.Factories;
using Client.Domain.Helpers; using Client.Domain.Helpers;
using Client.Domain.ViewModels; using Client.Domain.ViewModels;
@ -14,9 +15,9 @@ namespace Client.Domain.Service
{ {
public override void OnCreate(Hero entity) public override void OnCreate(Hero entity)
{ {
mainViewModel.CreateHero(entity);
entity.ExperienceInfo.ExpToLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level + 1); entity.ExperienceInfo.ExpToLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level + 1);
entity.ExperienceInfo.ExpToPrevLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level); entity.ExperienceInfo.ExpToPrevLevel = experienceHelper.GetExperienceToLevel(entity.ExperienceInfo.Level);
eventBus.Publish(new HeroCreatedEvent(entity));
} }
public override void OnUpdate(Hero entity) public override void OnUpdate(Hero entity)
@ -30,16 +31,16 @@ namespace Client.Domain.Service
public override void OnDelete(Hero entity) public override void OnDelete(Hero entity)
{ {
mainViewModel.DeleteHero(); eventBus.Publish(new HeroDeletedEvent());
} }
public HeroHandler(EntityFactoryInterface<Hero> factory, MainViewModelInterface mainViewModel, ExperienceHelperInterface experienceHelper) : base(factory) public HeroHandler(EntityFactoryInterface<Hero> factory, EventBusInterface eventBus, ExperienceHelperInterface experienceHelper) : base(factory)
{ {
this.mainViewModel = mainViewModel; this.eventBus = eventBus;
this.experienceHelper = experienceHelper; this.experienceHelper = experienceHelper;
} }
private readonly MainViewModelInterface mainViewModel; private readonly EventBusInterface eventBus;
private readonly ExperienceHelperInterface experienceHelper; private readonly ExperienceHelperInterface experienceHelper;
} }
} }

View File

@ -1,4 +1,5 @@
using Client.Domain.Entities; using Client.Domain.Entities;
using Client.Domain.Events;
using Client.Domain.Factories; using Client.Domain.Factories;
using Client.Domain.Helpers; using Client.Domain.Helpers;
using Client.Domain.ViewModels; using Client.Domain.ViewModels;
@ -14,22 +15,22 @@ namespace Client.Domain.Service
{ {
public override void OnCreate(NPC entity) public override void OnCreate(NPC entity)
{ {
mainViewModel.AddNpc(entity);
entity.Level = npcInfoHelper.GetLevel(entity.NpcId); entity.Level = npcInfoHelper.GetLevel(entity.NpcId);
entity.AggroRadius = npcInfoHelper.GetAggroRadius(entity.NpcId); entity.AggroRadius = npcInfoHelper.GetAggroRadius(entity.NpcId);
eventBus.Publish(new NpcCreatedEvent(entity));
} }
public override void OnDelete(NPC entity) public override void OnDelete(NPC entity)
{ {
mainViewModel.RemoveNpc(entity); eventBus.Publish(new NpcDeletedEvent(entity.Id));
} }
public NpcHandler(EntityFactoryInterface<NPC> factory, MainViewModelInterface mainViewModel, NpcInfoHelperInterface npcInfoHelper) : base(factory) public NpcHandler(EntityFactoryInterface<NPC> factory, EventBusInterface eventBus, NpcInfoHelperInterface npcInfoHelper) : base(factory)
{ {
this.mainViewModel = mainViewModel; this.eventBus = eventBus;
this.npcInfoHelper = npcInfoHelper; this.npcInfoHelper = npcInfoHelper;
} }
private readonly MainViewModelInterface mainViewModel; private readonly EventBusInterface eventBus;
private readonly NpcInfoHelperInterface npcInfoHelper; private readonly NpcInfoHelperInterface npcInfoHelper;
} }
} }

View File

@ -12,10 +12,6 @@ namespace Client.Domain.ViewModels
public interface MainViewModelInterface public interface MainViewModelInterface
{ {
void AddChatMessage(ChatMessage chatMessage); void AddChatMessage(ChatMessage chatMessage);
void CreateHero(Hero hero);
void DeleteHero();
void AddNpc(NPC npc);
void RemoveNpc(NPC npc);
void AddPlayer(Player player); void AddPlayer(Player player);
void RemovePlayer(Player player); void RemovePlayer(Player player);
void AddDrop(Drop drop); void AddDrop(Drop drop);

View File

@ -0,0 +1,49 @@
using Client.Domain.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
namespace Client.Infrastructure.Events
{
public class InMemoryEventBus : EventBusInterface
{
public void Publish<T>(T @event) where T : EventInterface
{
var type = @event.GetType();
if (subscribers.ContainsKey(type))
{
foreach (var subscriber in subscribers[type])
{
(subscriber as EventHandlerInterface<T>)?.Handle(@event);
}
}
}
public void Subscrbe<T>(EventHandlerInterface<T> handler) where T : EventInterface
{
var type = typeof(T);
if (!subscribers.ContainsKey(type))
{
subscribers[type] = new List<EventHandlerInterface>();
}
subscribers[type].Add(handler);
}
public void Unsubscrbe<T>(EventHandlerInterface<T> handler) where T : EventInterface
{
var type = typeof(T);
if (subscribers.ContainsKey(type))
{
subscribers[type].Remove(handler);
}
}
private Dictionary<Type, List<EventHandlerInterface>> subscribers = new Dictionary<Type, List<EventHandlerInterface>>();
}
}