// // 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; private bool _initialized; /// /// 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 Optional PacketSend => GetHook(IHookManager.PacketSendName); /// public Optional PacketReceive => GetHook(IHookManager.PacketReceiveName); /// public Optional PlayerWalk => GetHook(IHookManager.CharacterWalkName); /// public Optional EntityFollow => GetHook(IHookManager.EntityFollowName); /// public Optional EntityUnfollow => GetHook(IHookManager.EntityUnfollowName); /// public Optional PetWalk => GetHook(IHookManager.PetWalkName); /// public Optional EntityFocus => GetHook(IHookManager.EntityFocusName); /// public Optional Periodic => GetHook(IHookManager.PeriodicName); /// public IReadOnlyList Hooks => _hooks.Values.ToList(); /// public IResult Initialize(NosBindingManager bindingManager, NosBrowserManager browserManager) { _initialized = true; var (hooks, result) = _sharedHookManager.InitializeInstance(bindingManager, browserManager, _options); _hooks = hooks; return result; } /// public void Enable(IEnumerable names) { foreach (var name in names) { var hook = GetHook(name); hook.TryDo(h => h.Enable()); } } /// public void Disable(IEnumerable names) { foreach (var name in names) { var hook = GetHook(name); hook.TryDo(h => h.Disable()); } } /// public void DisableAll() { foreach (var hook in _hooks.Values) { hook.Disable(); } } /// public void EnableAll() { foreach (var hook in _hooks.Values) { hook.Enable(); } } /// public bool IsHookLoaded() where THook : INostaleHook => IsHookLoaded(typeof(THook)); /// public bool IsHookUsable() where THook : INostaleHook => IsHookUsable(typeof(THook)); /// public bool IsHookLoaded(Type hookType) => GetHook(hookType).IsPresent; /// public bool IsHookUsable(Type hookType) => GetHook(hookType).TryGet(out var h) && h.IsUsable; private Optional GetHook(string name) where T : INostaleHook { if (!_initialized) { throw new InvalidOperationException ($"Could not load hook {typeof(T)}. Did you forget to call IHookManager.Initialize?"); } var hook = _hooks.Values.FirstOrDefault(x => x is T); if (hook is not T typed) { return Optional.Empty; } return typed; } private Optional GetHook(Type hookType) { if (!_initialized) { throw new InvalidOperationException ($"Could not load hook {hookType.Name}. Did you forget to call IHookManager.Initialize?"); } var hook = _hooks.Values.FirstOrDefault(hookType.IsInstanceOfType); if (hook is null) { return Optional.Empty; } return new Optional(hook); } }