// // 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) { var result = _underlyingManager.Initialize(bindingManager, browserManager); _initialized = true; if (!result.IsSuccess) { return Result>.FromError(result.Error); } } 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; } }