From 69c46f6f0b73dd4475ee75d44f8783c9a45c262e Mon Sep 17 00:00:00 2001 From: Rutherther Date: Mon, 2 Jan 2023 21:39:28 +0100 Subject: [PATCH] feat(shared): add sharing of NosSmooth hooks --- .../EventArgs/HookStateEventArgs.cs | 25 +++ .../Extensions/ServiceCollectionExtensions.cs | 82 +++++---- .../Hooks/SharedHookManager.cs | 174 ++++++++++++++++++ .../Hooks/SingleHook.cs | 86 +++++++++ .../Hooks/SingleHookManager.cs | 125 +++++++++++++ .../Hooks/Specific/EntityFocusHook.cs | 24 +++ .../Hooks/Specific/EntityFollowHook.cs | 24 +++ .../Hooks/Specific/EntityUnfollowHook.cs | 24 +++ .../Hooks/Specific/PacketReceiveHook.cs | 24 +++ .../Hooks/Specific/PacketSendHook.cs | 24 +++ .../Hooks/Specific/PeriodicHook.cs | 26 +++ .../Hooks/Specific/PetWalkHook.cs | 23 +++ .../Hooks/Specific/PlayerWalkHook.cs | 23 +++ .../NosSmooth.Extensions.SharedBinding.csproj | 1 + .../SharedManager.cs | 55 ++---- .../SharedOptions.cs | 28 ++- 16 files changed, 679 insertions(+), 89 deletions(-) create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/EventArgs/HookStateEventArgs.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SharedHookManager.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHookManager.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFocusHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFollowHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityUnfollowHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketReceiveHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketSendHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PeriodicHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PetWalkHook.cs create mode 100644 src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PlayerWalkHook.cs diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/EventArgs/HookStateEventArgs.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/EventArgs/HookStateEventArgs.cs new file mode 100644 index 0000000000000000000000000000000000000000..e22ab505fe917026e01f8f4ea47134aba0c376f2 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/EventArgs/HookStateEventArgs.cs @@ -0,0 +1,25 @@ +// +// HookStateEventArgs.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace NosSmooth.Extensions.SharedBinding.EventArgs; + +/// +public class HookStateEventArgs : System.EventArgs +{ + /// + /// Initializes a new instance of the class. + /// + /// The new state. + public HookStateEventArgs(bool enabled) + { + Enabled = enabled; + } + + /// + /// Gets the new state. + /// + public bool Enabled { get; } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs index b015dfdc624d9fc484d06e1e3496209080aa33b1..0db188f3dbd10553f87b1bb73cd76b8dd1dceb34 100644 --- a/src/Extensions/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Extensions/ServiceCollectionExtensions.cs @@ -4,10 +4,13 @@ // Copyright (c) František Boháček. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Diagnostics; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using NosSmooth.Data.NOSFiles; +using NosSmooth.Extensions.SharedBinding.Hooks; using NosSmooth.LocalBinding; +using NosSmooth.LocalBinding.Hooks; using NosSmooth.PacketSerializer.Packets; namespace NosSmooth.Extensions.SharedBinding.Extensions; @@ -18,81 +21,80 @@ namespace NosSmooth.Extensions.SharedBinding.Extensions; public static class ServiceCollectionExtensions { /// - /// Replaces - /// with shared equivalent. That allows for multiple programs injected inside NosTale. + /// Adds shared . /// /// The collection. /// The same collection. - public static IServiceCollection ShareBinding(this IServiceCollection serviceCollection) + public static IServiceCollection ShareHooks(this IServiceCollection serviceCollection) { var original = serviceCollection - .Last(x => x.ServiceType == typeof(NosBindingManager)); + .Last(x => x.ServiceType == typeof(IHookManager)); + serviceCollection.Configure(o => o.AddDescriptor(original)); return serviceCollection - .Configure(o => o.BindingDescriptor = original) - .Replace - (ServiceDescriptor.Singleton(p => SharedManager.Instance.GetNosBindingManager(p))); + .AddSingleton + ( + p => + { + var sharedHookManager = p.GetRequiredService().GetShared(p); + return new SharedHookManager(sharedHookManager); + } + ) + .Replace(ServiceDescriptor.Singleton()); } /// - /// Replaces + /// Replaces /// with shared equivalent. That allows for multiple programs injected inside NosTale. /// /// The collection. + /// The shared type. /// The same collection. - public static IServiceCollection ShareFileManager(this IServiceCollection serviceCollection) + public static IServiceCollection Share(this IServiceCollection serviceCollection) + where T : class { var original = serviceCollection - .Last(x => x.ServiceType == typeof(NostaleDataFilesManager)); + .Last(x => x.ServiceType == typeof(T)); return serviceCollection - .Configure(o => o.FileDescriptor = original) + .Configure(o => o.AddDescriptor(original)) .Replace - (ServiceDescriptor.Singleton(p => SharedManager.Instance.GetFilesManager(p))); + ( + ServiceDescriptor.Singleton(p => SharedManager.Instance.GetShared(p)) + ); } /// - /// Replaces + /// Tries to replace /// with shared equivalent. That allows for multiple programs injected inside NosTale. /// /// The collection. + /// The shared type. /// The same collection. - public static IServiceCollection SharePacketRepository(this IServiceCollection serviceCollection) + public static IServiceCollection TryShare(this IServiceCollection serviceCollection) + where T : class { - var original = serviceCollection - .Last(x => x.ServiceType == typeof(IPacketTypesRepository)); + if (serviceCollection.Any(x => x.ServiceType == typeof(T))) + { + return serviceCollection.Share(); + } - return serviceCollection - .Configure(o => o.PacketRepositoryDescriptor = original) - .Replace - ( - ServiceDescriptor.Singleton(p => SharedManager.Instance.GetPacketRepository(p)) - ); + return serviceCollection; } /// - /// Replaces , and - /// with their shared equvivalents. That allows for multiple programs injected inside NosTale. + /// Replaces some NosSmooth types with their shared equivalents. + /// That allows for multiple programs injected inside NosTale. /// /// The collection. /// The same collection. public static IServiceCollection ShareNosSmooth(this IServiceCollection serviceCollection) { - if (serviceCollection.Any(x => x.ServiceType == typeof(NosBindingManager))) - { - serviceCollection.ShareBinding(); - } - - if (serviceCollection.Any(x => x.ServiceType == typeof(NostaleDataFilesManager))) - { - serviceCollection.ShareFileManager(); - } - - if (serviceCollection.Any(x => x.ServiceType == typeof(IPacketTypesRepository))) - { - serviceCollection.SharePacketRepository(); - } - - return serviceCollection; + return serviceCollection + .AddSingleton(p => SharedManager.Instance) + .ShareHooks() + .TryShare() + .TryShare() + .TryShare(); } } \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SharedHookManager.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SharedHookManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..73df23374ccd0977f00b962e6103a688963affd6 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SharedHookManager.cs @@ -0,0 +1,174 @@ +// +// SharedHookManager.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.Extensions.SharedBinding.Hooks.Specific; +using NosSmooth.LocalBinding; +using NosSmooth.LocalBinding.Hooks; +using NosSmooth.LocalBinding.Options; +using Remora.Results; + +namespace NosSmooth.Extensions.SharedBinding.Hooks; + +/// +/// A hook manager managing s of all of the instances. +/// +public class SharedHookManager +{ + private readonly IHookManager _underlyingManager; + + private bool _initialized; + private Dictionary _hookedCount; + + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook manager. + /// The binding manager. + /// The browser manager. + public SharedHookManager + ( + IHookManager underlyingManager + ) + { + _hookedCount = new Dictionary(); + _underlyingManager = underlyingManager; + } + + /// + /// Initialize a shared NosSmooth instance. + /// + /// The binding manager. + /// The browser manager. + /// The initial options to be respected. + /// The dictionary containing all of the hooks. + public Result> InitializeInstance + (NosBindingManager bindingManager, NosBrowserManager browserManager, HookManagerOptions options) + { + if (!_initialized) + { + _underlyingManager.Initialize(bindingManager, browserManager); + _initialized = true; + } + + var hooks = new Dictionary(); + + // TODO: initialize using reflection + hooks.Add + ( + _underlyingManager.Periodic.Name, + InitializeSingleHook + ( + new PeriodicHook(_underlyingManager.Periodic), + options.PeriodicHook + ) + ); + + hooks.Add + ( + _underlyingManager.EntityFocus.Name, + InitializeSingleHook + ( + new EntityFocusHook(_underlyingManager.EntityFocus), + options.EntityFocusHook + ) + ); + + hooks.Add + ( + _underlyingManager.EntityFollow.Name, + InitializeSingleHook + ( + new EntityFollowHook(_underlyingManager.EntityFollow), + options.EntityFollowHook + ) + ); + + hooks.Add + ( + _underlyingManager.EntityUnfollow.Name, + InitializeSingleHook + ( + new EntityUnfollowHook(_underlyingManager.EntityUnfollow), + options.EntityUnfollowHook + ) + ); + + hooks.Add + ( + _underlyingManager.PacketReceive.Name, + InitializeSingleHook + ( + new PacketReceiveHook(_underlyingManager.PacketReceive), + options.PacketReceiveHook + ) + ); + + hooks.Add + ( + _underlyingManager.PacketSend.Name, + InitializeSingleHook + ( + new PacketSendHook(_underlyingManager.PacketSend), + options.PacketSendHook + ) + ); + + hooks.Add + ( + _underlyingManager.PetWalk.Name, + InitializeSingleHook + ( + new PetWalkHook(_underlyingManager.PetWalk), + options.PetWalkHook + ) + ); + + hooks.Add + ( + _underlyingManager.PlayerWalk.Name, + InitializeSingleHook + ( + new PlayerWalkHook(_underlyingManager.PlayerWalk), + options.PlayerWalkHook + ) + ); + + return hooks; + } + + private INostaleHook InitializeSingleHook(SingleHook hook, HookOptions options) + where TFunction : Delegate + where TWrapperFunction : Delegate + where TEventArgs : System.EventArgs + { + hook.StateChanged += (_, state) => + { + if (!_hookedCount.ContainsKey(hook.Name)) + { + _hookedCount[hook.Name] = 0; + } + + _hookedCount[hook.Name] += state.Enabled ? 1 : -1; + + if (state.Enabled) + { + _underlyingManager.Enable(new[] { hook.Name }); + } + else if (_hookedCount[hook.Name] == 0) + { + _underlyingManager.Disable(new[] { hook.Name }); + } + }; + + if (options.Hook) + { + hook.Enable(); + } + + return hook; + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..0906bafe4cd9458255e70c109c6c0638071d02b3 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHook.cs @@ -0,0 +1,86 @@ +// +// SingleHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.ComponentModel; +using NosSmooth.Extensions.SharedBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; +using Remora.Results; + +namespace NosSmooth.Extensions.SharedBinding.Hooks; + +/// +/// A hook for a single instance of NosSmooth sharing with the rest of application. +/// +/// The function delegate. +/// A wrapper function that abstracts the call to original function. May get the neccessary object to call the function and accept only relevant arguments. +/// The event args used in case of a call. +public class SingleHook : INostaleHook + where TFunction : Delegate + where TWrapperFunction : Delegate + where TEventArgs : System.EventArgs +{ + private readonly INostaleHook _underlyingHook; + + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public SingleHook(INostaleHook underlyingHook) + { + _underlyingHook = underlyingHook; + } + + /// + /// Called upon Enable or Disable. + /// + public event EventHandler? StateChanged; + + /// + public string Name => _underlyingHook.Name; + + /// + public bool IsEnabled { get; private set; } + + /// + public Result Enable() + { + if (!IsEnabled) + { + IsEnabled = true; + StateChanged?.Invoke(this, new HookStateEventArgs(true)); + _underlyingHook.Called += FireCalled; + } + + return Result.FromSuccess(); + } + + /// + public Result Disable() + { + if (IsEnabled) + { + IsEnabled = true; + StateChanged?.Invoke(this, new HookStateEventArgs(false)); + _underlyingHook.Called -= FireCalled; + } + + return Result.FromSuccess(); + } + + private void FireCalled(object? owner, TEventArgs eventArgs) + { + Called?.Invoke(this, eventArgs); + } + + /// + public TWrapperFunction WrapperFunction => _underlyingHook.WrapperFunction; + + /// + public TFunction OriginalFunction => _underlyingHook.OriginalFunction; + + /// + public event EventHandler? Called; +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHookManager.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHookManager.cs new file mode 100644 index 0000000000000000000000000000000000000000..ca36d63a17bf602662e20738f39766be488120b4 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/SingleHookManager.cs @@ -0,0 +1,125 @@ +// +// SingleHookManager.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.Extensions.Options; +using NosSmooth.LocalBinding; +using NosSmooth.LocalBinding.Hooks; +using NosSmooth.LocalBinding.Options; +using Remora.Results; + +namespace NosSmooth.Extensions.SharedBinding.Hooks; + +/// +/// A hook manager for a single NosSmooth instance using shared data. +/// +public class SingleHookManager : IHookManager +{ + private readonly SharedHookManager _sharedHookManager; + private readonly HookManagerOptions _options; + private Dictionary _hooks; + + /// + /// Initializes a new instance of the class. + /// + /// The shared hook manager. + /// The hook options. + public SingleHookManager(SharedHookManager sharedHookManager, IOptions options) + { + _hooks = new Dictionary(); + _sharedHookManager = sharedHookManager; + _options = options.Value; + } + + /// + public IPacketSendHook PacketSend => GetHook(IHookManager.PacketSendName); + + /// + public IPacketReceiveHook PacketReceive => GetHook(IHookManager.PacketReceiveName); + + /// + public IPlayerWalkHook PlayerWalk => GetHook(IHookManager.CharacterWalkName); + + /// + public IEntityFollowHook EntityFollow => GetHook(IHookManager.EntityFollowName); + + /// + public IEntityUnfollowHook EntityUnfollow => GetHook(IHookManager.EntityUnfollowName); + + /// + public IPetWalkHook PetWalk => GetHook(IHookManager.PetWalkName); + + /// + public IEntityFocusHook EntityFocus => GetHook(IHookManager.EntityFocusName); + + /// + public IPeriodicHook Periodic => GetHook(IHookManager.PeriodicName); + + /// + public IReadOnlyList Hooks => _hooks.Values.ToList(); + + /// + public IResult Initialize(NosBindingManager bindingManager, NosBrowserManager browserManager) + { + var hooksResult = _sharedHookManager.InitializeInstance(bindingManager, browserManager, _options); + if (!hooksResult.IsDefined(out var hooks)) + { + return hooksResult; + } + + _hooks = hooks; + return Result.FromSuccess(); + } + + /// + public void Enable(IEnumerable names) + { + foreach (var name in names) + { + var hook = GetHook(name); + hook.Enable(); + } + } + + /// + public void Disable(IEnumerable names) + { + foreach (var name in names) + { + var hook = GetHook(name); + hook.Disable(); + } + } + + /// + public void DisableAll() + { + foreach (var hook in _hooks.Values) + { + hook.Disable(); + } + } + + /// + public void EnableAll() + { + foreach (var hook in _hooks.Values) + { + hook.Enable(); + } + } + + private T GetHook(string name) + where T : INostaleHook + { + if (!_hooks.ContainsKey(name) || _hooks[name] is not T typed) + { + throw new InvalidOperationException + ($"Could not load hook {name}. Did you forget to call IHookManager.Initialize?"); + } + + return typed; + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFocusHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFocusHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..b2f21b01b1c53a8485687bddb96455f50f159920 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFocusHook.cs @@ -0,0 +1,24 @@ +// +// EntityFocusHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class EntityFocusHook : SingleHook, IEntityFocusHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public EntityFocusHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFollowHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFollowHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..c9206e55daf7aa7c694f340a3893f9db3c84af30 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityFollowHook.cs @@ -0,0 +1,24 @@ +// +// EntityFollowHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class EntityFollowHook : SingleHook, IEntityFollowHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public EntityFollowHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityUnfollowHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityUnfollowHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..7becba71a364c6752261b893fd84e43d5bea7010 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/EntityUnfollowHook.cs @@ -0,0 +1,24 @@ +// +// EntityUnfollowHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class EntityUnfollowHook : SingleHook, IEntityUnfollowHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public EntityUnfollowHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketReceiveHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketReceiveHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..6ca2a4f4ae95a0b047e77a16203768c26e62190d --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketReceiveHook.cs @@ -0,0 +1,24 @@ +// +// PacketReceiveHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class PacketReceiveHook : SingleHook, IPacketReceiveHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public PacketReceiveHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketSendHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketSendHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..3bf68eff5a6866d80d82c72ff5808221c3d474ed --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PacketSendHook.cs @@ -0,0 +1,24 @@ +// +// PacketSendHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class PacketSendHook : SingleHook, IPacketSendHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public PacketSendHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PeriodicHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PeriodicHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..1ee8fa7f979962033a88553aaee8b7b25356c669 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PeriodicHook.cs @@ -0,0 +1,26 @@ +// +// PeriodicHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +/// A hook of a periodic function, +/// preferably called every frame. +/// +internal class PeriodicHook : + SingleHook, IPeriodicHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public PeriodicHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PetWalkHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PetWalkHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..8b5ed4bdb4061c61ba4cb72e0312b028f730181d --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PetWalkHook.cs @@ -0,0 +1,23 @@ +// +// PetWalkHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class PetWalkHook : SingleHook, IPetWalkHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public PetWalkHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PlayerWalkHook.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PlayerWalkHook.cs new file mode 100644 index 0000000000000000000000000000000000000000..dd68caa5acbf731b2bd1ae317138ce2af3c7a303 --- /dev/null +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/Hooks/Specific/PlayerWalkHook.cs @@ -0,0 +1,23 @@ +// +// PlayerWalkHook.cs +// +// Copyright (c) František Boháček. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using NosSmooth.LocalBinding.EventArgs; +using NosSmooth.LocalBinding.Hooks; + +namespace NosSmooth.Extensions.SharedBinding.Hooks.Specific; + +/// +internal class PlayerWalkHook : SingleHook, IPlayerWalkHook +{ + /// + /// Initializes a new instance of the class. + /// + /// The underlying hook. + public PlayerWalkHook(INostaleHook underlyingHook) + : base(underlyingHook) + { + } +} \ No newline at end of file diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj b/src/Extensions/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj index f65ecced4bb2eedb5b564117396686528432affb..43103fcfc5ff02f17d9d797068cf9ba32d551c2c 100644 --- a/src/Extensions/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/NosSmooth.Extensions.SharedBinding.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedManager.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedManager.cs index 2eeb8627f580f7d01894661d5bf2ef4183764b75..b48623bfe264fea4a4f61f5ba488852d731c7900 100644 --- a/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedManager.cs +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedManager.cs @@ -20,9 +20,7 @@ namespace NosSmooth.Extensions.SharedBinding; public class SharedManager { private static SharedManager? _instance; - private NosBindingManager? _bindingManager; - private NostaleDataFilesManager? _filesManager; - private IPacketTypesRepository? _packetRepository; + private Dictionary _sharedData = new(); /// /// A singleton instance. @@ -41,58 +39,33 @@ public class SharedManager } } - /// - /// Gets the shared nos binding manager. - /// - /// The service provider. - /// The shared manager. - public NosBindingManager GetNosBindingManager(IServiceProvider services) - { - if (_bindingManager is null) - { - _bindingManager = GetFromDescriptor(services, o => o.BindingDescriptor); - } - - return _bindingManager; - - } - - /// - /// Gets the shared file manager. - /// - /// The service provider. - /// The shared manager. - public NostaleDataFilesManager GetFilesManager(IServiceProvider services) + private SharedManager() { - if (_filesManager is null) - { - _filesManager = GetFromDescriptor(services, o => o.FileDescriptor); - } - - return _filesManager; - } /// - /// Gets the shared packet type repository. + /// Get shared equivalent of the given type. /// /// The service provider. - /// The shared repository. - public IPacketTypesRepository GetPacketRepository(IServiceProvider services) + /// The type to get shared instance of. + /// The shared instance. + /// Thrown in case the type is not shared. + public T GetShared(IServiceProvider services) + where T : class { - if (_packetRepository is null) + if (!_sharedData.ContainsKey(typeof(T))) { - _packetRepository = GetFromDescriptor(services, o => o.PacketRepositoryDescriptor); + _sharedData[typeof(T)] = CreateShared(services); } - return _packetRepository; - + return (T)_sharedData[typeof(T)]; } - private T GetFromDescriptor(IServiceProvider services, Func getDescriptor) + private T CreateShared(IServiceProvider services) + where T : class { var options = services.GetRequiredService>(); - var descriptor = getDescriptor(options.Value); + var descriptor = options.Value.GetDescriptor(typeof(T)); if (descriptor is null) { diff --git a/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedOptions.cs b/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedOptions.cs index 184d55bdcc78208136dec49666626c88c8ecb09f..d45f08541020e628fd6ad5aac09e4fec0b3f39b4 100644 --- a/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedOptions.cs +++ b/src/Extensions/NosSmooth.Extensions.SharedBinding/SharedOptions.cs @@ -16,18 +16,30 @@ namespace NosSmooth.Extensions.SharedBinding; /// internal class SharedOptions { - /// - /// Gets or sets the original descriptor of . - /// - public ServiceDescriptor? BindingDescriptor { get; set; } + private Dictionary _descriptors = new(); /// - /// Gets or sets the original descriptor of . + /// Add service descriptor for given type. /// - public ServiceDescriptor? FileDescriptor { get; set; } + /// The service descriptor. + public void AddDescriptor(ServiceDescriptor descriptor) + { + var type = descriptor.ServiceType; + if (_descriptors.ContainsKey(type)) + { + return; + } + + _descriptors[type] = descriptor; + } /// - /// Gets or sets the original descriptor of . + /// Get descriptor for the given type. /// - public ServiceDescriptor? PacketRepositoryDescriptor { get; set; } + /// The type of the descriptor. + /// A descriptor. + public ServiceDescriptor GetDescriptor(Type type) + { + return _descriptors[type]; + } } \ No newline at end of file