M src/Core/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs => src/Core/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs +14 -0
@@ 41,4 41,18 @@ public static class ServiceCollectionExtensions
.AddSingleton(p => p.GetRequiredService<NosBindingManager>().UnitManager)
.AddSingleton(p => p.GetRequiredService<NosBindingManager>().Network);
}
+
+ /// <summary>
+ /// Configures what functions to hook and allows the user to make pattern, offset changes.
+ /// </summary>
+ /// <param name="serviceCollection">The service collection.</param>
+ /// <param name="configure">Function for configuring the hook config.</param>
+ /// <returns>The collection.</returns>
+ public static IServiceCollection ConfigureHooks(this IServiceCollection serviceCollection, Action<HooksConfigBuilder> configure)
+ {
+ var builder = new HooksConfigBuilder();
+ configure(builder);
+ builder.Apply(serviceCollection);
+ return serviceCollection;
+ }
}=
\ No newline at end of file
A src/Core/NosSmooth.LocalBinding/HookOptions.cs => src/Core/NosSmooth.LocalBinding/HookOptions.cs +15 -0
@@ 0,0 1,15 @@
+//
+// HookOptions.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.LocalBinding;
+
+/// <summary>
+/// A configuration for hooking a function.
+/// </summary>
+/// <param name="Hook">Whether to hook the function.</param>
+/// <param name="MemoryPattern">The memory pattern in hex. Use ?? for any bytes.</param>
+/// <param name="Offset">The offset to find the function at.</param>
+public record HookOptions(bool Hook, string MemoryPattern, int Offset);<
\ No newline at end of file
A src/Core/NosSmooth.LocalBinding/HookOptionsBuilder.cs => src/Core/NosSmooth.LocalBinding/HookOptionsBuilder.cs +83 -0
@@ 0,0 1,83 @@
+//
+// HookOptionsBuilder.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.LocalBinding;
+
+/// <summary>
+/// Builder for <see cref="HookOptions"/>.
+/// </summary>
+public class HookOptionsBuilder
+{
+ private bool _hook;
+ private string _pattern;
+ private int _offset;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HookOptionsBuilder"/> class.
+ /// </summary>
+ /// <param name="options">The options.</param>
+ internal HookOptionsBuilder(HookOptions options)
+ {
+ _hook = options.Hook;
+ _pattern = options.MemoryPattern;
+ _offset = options.Offset;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HookOptionsBuilder"/> class.
+ /// </summary>
+ /// <param name="hook">Whether to hook the function.</param>
+ /// <param name="pattern">The default pattern.</param>
+ /// <param name="offset">The default offset.</param>
+ internal HookOptionsBuilder(bool hook, string pattern, int offset)
+ {
+ _offset = offset;
+ _pattern = pattern;
+ _hook = hook;
+ }
+
+ /// <summary>
+ /// Configure whether to hook this function.
+ /// Default true.
+ /// </summary>
+ /// <param name="hook">Whether to hook the function.</param>
+ /// <returns>This builder.</returns>
+ public HookOptionsBuilder Hook(bool hook = true)
+ {
+ _hook = hook;
+ return this;
+ }
+
+ /// <summary>
+ /// Configure the memory pattern.
+ /// Use ?? for any bytes.
+ /// </summary>
+ /// <param name="pattern">The memory pattern.</param>
+ /// <returns>This builder.</returns>
+ public HookOptionsBuilder MemoryPattern(string pattern)
+ {
+ _pattern = pattern;
+ return this;
+ }
+
+ /// <summary>
+ /// Configure the offset from the pattern.
+ /// </summary>
+ /// <param name="offset">The offset.</param>
+ /// <returns>This builder.</returns>
+ public HookOptionsBuilder Offset(int offset)
+ {
+ _offset = offset;
+ return this;
+ }
+
+ /// <summary>
+ /// Create hook options from this builder.
+ /// </summary>
+ /// <returns>The options.</returns>
+ internal HookOptions Build()
+ => new HookOptions(_hook, _pattern, _offset);
+}<
\ No newline at end of file
A src/Core/NosSmooth.LocalBinding/HooksConfigBuilder.cs => src/Core/NosSmooth.LocalBinding/HooksConfigBuilder.cs +290 -0
@@ 0,0 1,290 @@
+//
+// HooksConfigBuilder.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.DependencyInjection;
+using NosSmooth.LocalBinding.Options;
+
+namespace NosSmooth.LocalBinding;
+
+/// <summary>
+/// Provides user-friendly builder for configuring
+/// the hooks.
+/// </summary>
+/// <remarks>
+/// Use this by invoking .ConfigureHooks on IServiceCollection.
+///
+/// May change hook's pattern or offset as well as enable or disable
+/// hooking altogether.
+///
+/// By default, networking (packet send, packet receive) hooking is enabled,
+/// everything else is disabled.
+///
+/// The methods may be chained, you may call HookAll() and then start disabling
+/// the ones you don't need.
+/// </remarks>
+public class HooksConfigBuilder
+{
+ private readonly HookOptionsBuilder _packetSendHook;
+ private readonly HookOptionsBuilder _packetReceiveHook;
+ private readonly HookOptionsBuilder _playerWalkHook;
+ private readonly HookOptionsBuilder _petWalkHook;
+ private readonly HookOptionsBuilder _entityFocusHook;
+ private readonly HookOptionsBuilder _entityFollowHook;
+ private readonly HookOptionsBuilder _entityUnfollowHook;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="HooksConfigBuilder"/> class.
+ /// </summary>
+ internal HooksConfigBuilder()
+ {
+ _playerWalkHook = new HookOptionsBuilder(new CharacterBindingOptions().WalkHook);
+ _packetSendHook = new HookOptionsBuilder(new NetworkBindingOptions().PacketSendHook);
+ _packetReceiveHook = new HookOptionsBuilder(new NetworkBindingOptions().PacketReceiveHook);
+ _petWalkHook = new HookOptionsBuilder(new PetManagerBindingOptions().PetWalkHook);
+ _entityFocusHook = new HookOptionsBuilder(new UnitManagerBindingOptions().EntityFocusHook);
+ _entityFollowHook = new HookOptionsBuilder(new CharacterBindingOptions().EntityFollowHook);
+ _entityUnfollowHook = new HookOptionsBuilder(new CharacterBindingOptions().EntityUnfollowHook);
+ }
+
+ /// <summary>
+ /// Disable all hooks.
+ /// </summary>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookNone()
+ {
+ _packetSendHook.Hook(false);
+ _packetReceiveHook.Hook(false);
+ _playerWalkHook.Hook(false);
+ _petWalkHook.Hook(false);
+ _entityFocusHook.Hook(false);
+ _entityFollowHook.Hook(false);
+ _entityUnfollowHook.Hook(false);
+ return this;
+ }
+
+ /// <summary>
+ /// Enable all hooks.
+ /// </summary>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookAll()
+ {
+ _packetSendHook.Hook(true);
+ _packetReceiveHook.Hook(true);
+ _playerWalkHook.Hook(true);
+ _petWalkHook.Hook(true);
+ _entityFocusHook.Hook(true);
+ _entityFollowHook.Hook(true);
+ _entityUnfollowHook.Hook(true);
+ return this;
+ }
+
+ /// <summary>
+ /// Enable networking (packet send, packet receive) hooks.
+ /// </summary>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookNetworking()
+ {
+ _packetSendHook.Hook(true);
+ _packetReceiveHook.Hook(true);
+ return this;
+ }
+
+ /// <summary>
+ /// Configure packet send hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookPacketSend(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _packetSendHook.Hook();
+ configure(_packetSendHook);
+ }
+ else
+ {
+ _packetSendHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure packet receive hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookPacketReceive(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _packetReceiveHook.Hook();
+ configure(_packetReceiveHook);
+ }
+ else
+ {
+ _packetReceiveHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure player walk hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookPlayerWalk(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _playerWalkHook.Hook();
+ configure(_playerWalkHook);
+ }
+ else
+ {
+ _playerWalkHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure pet walk hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookPetWalk(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _petWalkHook.Hook();
+ configure(_petWalkHook);
+ }
+ else
+ {
+ _petWalkHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure entity focus hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookEntityFocus(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _entityFocusHook.Hook();
+ configure(_entityFocusHook);
+ }
+ else
+ {
+ _entityFocusHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure entity follow hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookEntityFollow(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _entityFollowHook.Hook();
+ configure(_entityFollowHook);
+ }
+ else
+ {
+ _entityFollowHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Configure entity unfollow hooks.
+ /// Enables the hook. In case you just want to change the pattern or offset
+ /// and do not want to enable the hook, call .Hook(false) in the builder.
+ /// </summary>
+ /// <param name="configure">The configuring action.</param>
+ /// <returns>This builder.</returns>
+ public HooksConfigBuilder HookEntityUnfollow(Action<HookOptionsBuilder>? configure = default)
+ {
+ if (configure is not null)
+ {
+ _entityUnfollowHook.Hook();
+ configure(_entityUnfollowHook);
+ }
+ else
+ {
+ _entityUnfollowHook.Hook(true);
+ }
+
+ return this;
+ }
+
+ /// <summary>
+ /// Applies configurations to the given collection.
+ /// </summary>
+ /// <param name="serviceCollection">The service collection.</param>
+ internal void Apply(IServiceCollection serviceCollection)
+ {
+ serviceCollection.Configure<CharacterBindingOptions>
+ (
+ characterOptions =>
+ {
+ characterOptions.WalkHook = _playerWalkHook.Build();
+ characterOptions.EntityFollowHook = _entityFollowHook.Build();
+ characterOptions.EntityUnfollowHook = _entityUnfollowHook.Build();
+ }
+ );
+
+ serviceCollection.Configure<NetworkBindingOptions>
+ (
+ characterOptions =>
+ {
+ characterOptions.PacketReceiveHook = _packetReceiveHook.Build();
+ characterOptions.PacketSendHook = _packetSendHook.Build();
+ }
+ );
+
+ serviceCollection.Configure<PetManagerBindingOptions>
+ (
+ characterOptions =>
+ {
+ characterOptions.PetWalkHook = _petWalkHook.Build();
+ }
+ );
+
+ serviceCollection.Configure<UnitManagerBindingOptions>
+ (
+ characterOptions =>
+ {
+ characterOptions.EntityFocusHook = _entityFocusHook.Build();
+ }
+ );
+ }
+}<
\ No newline at end of file
M src/Core/NosSmooth.LocalBinding/NosBindingManager.cs => src/Core/NosSmooth.LocalBinding/NosBindingManager.cs +9 -12
@@ 307,7 307,7 @@ public class NosBindingManager : IDisposable
}
/// <summary>
- /// Disable the currently enabled nostale hooks.
+ /// Disable the currently enabled NosTale hooks.
/// </summary>
/// <returns>A result that may or may not have succeeded.</returns>
public Result DisableHooks()
@@ 336,24 336,20 @@ public class NosBindingManager : IDisposable
/// </summary>
/// <param name="name">The name of the binding.</param>
/// <param name="callbackFunction">The callback function to call instead of the original one.</param>
- /// <param name="pattern">The pattern.</param>
- /// <param name="offset">The offset from the pattern.</param>
- /// <param name="enableHook">Whether to activate the hook.</param>
+ /// <param name="options">The options for the function hook. (pattern, offset, whether to activate).</param>
/// <typeparam name="TFunction">The type of the function.</typeparam>
/// <returns>The hook object or an error.</returns>
internal Result<IHook<TFunction>> CreateHookFromPattern<TFunction>
(
string name,
TFunction callbackFunction,
- string pattern,
- int offset = 0,
- bool enableHook = true
+ HookOptions options
)
{
- var walkFunctionAddress = Scanner.FindPattern(pattern);
+ var walkFunctionAddress = Scanner.FindPattern(options.MemoryPattern);
if (!walkFunctionAddress.Found)
{
- return new BindingNotFoundError(pattern, name);
+ return new BindingNotFoundError(options.MemoryPattern, name);
}
try
@@ 361,11 357,12 @@ public class NosBindingManager : IDisposable
var hook = Hooks.CreateHook
(
callbackFunction,
- walkFunctionAddress.Offset + (int)_browserManager.Process.MainModule!.BaseAddress + offset
+ walkFunctionAddress.Offset + (int)_browserManager.Process.MainModule!.BaseAddress + options.Offset
);
- if (enableHook)
+ hook.Activate();
+ if (!options.Hook)
{
- hook.Activate();
+ hook.Disable();
}
return Result<IHook<TFunction>>.FromSuccess(hook);
M src/Core/NosSmooth.LocalBinding/Objects/NetworkBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/NetworkBinding.cs +20 -48
@@ 52,72 52,44 @@ public class NetworkBinding
return new BindingNotFoundError(options.NetworkObjectPattern, "NetworkBinding");
}
- var packetSendAddress = bindingManager.Scanner.FindPattern(options.SendFunctionPattern);
- if (!packetSendAddress.Found)
- {
- return new BindingNotFoundError(options.SendFunctionPattern, "NetworkBinding.SendPacket");
- }
-
- var packetReceiveAddress = bindingManager.Scanner.FindPattern(options.ReceiveFunctionPattern);
- if (!packetReceiveAddress.Found)
- {
- return new BindingNotFoundError(options.ReceiveFunctionPattern, "NetworkBinding.ReceivePacket");
- }
-
- var sendFunction = bindingManager.Hooks.CreateFunction<PacketSendDelegate>
- (packetSendAddress.Offset + (int)process.MainModule!.BaseAddress);
- var sendWrapper = sendFunction.GetWrapper();
-
- var receiveFunction = bindingManager.Hooks.CreateFunction<PacketReceiveDelegate>
- (packetReceiveAddress.Offset + (int)process.MainModule!.BaseAddress);
- var receiveWrapper = receiveFunction.GetWrapper();
-
var binding = new NetworkBinding
(
bindingManager,
- (nuint)(networkObjectAddress.Offset + (int)process.MainModule!.BaseAddress + 0x01),
- sendWrapper,
- receiveWrapper
+ (nuint)(networkObjectAddress.Offset + (int)process.MainModule!.BaseAddress + 0x01)
);
- if (options.HookSend)
+ var sendHookResult = bindingManager.CreateHookFromPattern<PacketSendDelegate>
+ ("NetworkBinding.SendPacket", binding.SendPacketDetour, options.PacketSendHook);
+ if (!sendHookResult.IsDefined(out var sendHook))
{
- binding._sendHook = sendFunction
- .Hook(binding.SendPacketDetour);
- binding._originalSend = binding._sendHook.OriginalFunction;
+ return Result<NetworkBinding>.FromError(sendHookResult);
}
- if (options.HookReceive)
+ var receiveHookResult = bindingManager.CreateHookFromPattern<PacketReceiveDelegate>
+ ("NetworkBinding.ReceivePacket", binding.ReceivePacketDetour, options.PacketReceiveHook);
+ if (!receiveHookResult.IsDefined(out var receiveHook))
{
- binding._receiveHook = receiveFunction
- .Hook(binding.ReceivePacketDetour);
- binding._originalReceive = binding._receiveHook.OriginalFunction;
+ return Result<NetworkBinding>.FromError(receiveHookResult);
}
- binding._sendHook?.Activate();
- binding._receiveHook?.Activate();
+ binding._sendHook = sendHook;
+ binding._receiveHook = receiveHook;
return binding;
}
private readonly NosBindingManager _bindingManager;
private readonly nuint _networkManagerAddress;
- private IHook<PacketSendDelegate>? _sendHook;
- private IHook<PacketReceiveDelegate>? _receiveHook;
- private PacketSendDelegate _originalSend;
- private PacketReceiveDelegate _originalReceive;
+ private IHook<PacketSendDelegate> _sendHook = null!;
+ private IHook<PacketReceiveDelegate> _receiveHook = null!;
private NetworkBinding
(
NosBindingManager bindingManager,
- nuint networkManagerAddress,
- PacketSendDelegate originalSend,
- PacketReceiveDelegate originalReceive
+ nuint networkManagerAddress
)
{
_bindingManager = bindingManager;
_networkManagerAddress = networkManagerAddress;
- _originalSend = originalSend;
- _originalReceive = originalReceive;
}
/// <summary>
@@ 146,7 118,7 @@ public class NetworkBinding
try
{
using var nostaleString = NostaleStringA.Create(_bindingManager.Memory, packet);
- _originalSend(GetManagerAddress(false), nostaleString.Get());
+ _sendHook.OriginalFunction(GetManagerAddress(false), nostaleString.Get());
}
catch (Exception e)
{
@@ 166,7 138,7 @@ public class NetworkBinding
try
{
using var nostaleString = NostaleStringA.Create(_bindingManager.Memory, packet);
- _originalReceive(GetManagerAddress(true), nostaleString.Get());
+ _receiveHook.OriginalFunction(GetManagerAddress(true), nostaleString.Get());
}
catch (Exception e)
{
@@ 207,14 179,14 @@ public class NetworkBinding
var packet = Marshal.PtrToStringAnsi((IntPtr)packetString);
if (packet is null)
{ // ?
- _originalSend(packetObject, packetString);
+ _sendHook.OriginalFunction(packetObject, packetString);
}
else
{
var result = PacketSend?.Invoke(packet);
if (result ?? true)
{
- _originalSend(packetObject, packetString);
+ _sendHook.OriginalFunction(packetObject, packetString);
}
}
}
@@ 226,7 198,7 @@ public class NetworkBinding
var packet = Marshal.PtrToStringAnsi((IntPtr)packetString);
if (packet is null)
{ // ?
- _originalReceive(packetObject, packetString);
+ _receiveHook.OriginalFunction(packetObject, packetString);
}
else
{
@@ 240,7 212,7 @@ public class NetworkBinding
// TODO FIX THIS correctly
if (_receivedCancel || !packet.StartsWith("cancel"))
{
- _originalReceive(packetObject, packetString);
+ _receiveHook.OriginalFunction(packetObject, packetString);
}
else
{
M src/Core/NosSmooth.LocalBinding/Objects/PetManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/PetManagerBinding.cs +1 -2
@@ 35,8 35,7 @@ public class PetManagerBinding
(
"PetManagerBinding.PetWalk",
petManager.PetWalkDetour,
- options.PetWalkPattern,
- enableHook: options.HookPetWalk
+ options.PetWalkHook
);
if (!hookResult.IsSuccess)
M src/Core/NosSmooth.LocalBinding/Objects/PlayerManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/PlayerManagerBinding.cs +26 -69
@@ 61,96 61,53 @@ public class PlayerManagerBinding
/// <returns>A network binding or an error.</returns>
public static Result<PlayerManagerBinding> Create(NosBindingManager bindingManager, PlayerManager playerManager, CharacterBindingOptions options)
{
- var process = Process.GetCurrentProcess();
-
- var walkFunctionAddress = bindingManager.Scanner.FindPattern(options.WalkFunctionPattern);
- if (!walkFunctionAddress.Found)
- {
- return new BindingNotFoundError(options.WalkFunctionPattern, "CharacterBinding.Walk");
- }
-
- var followEntityAddress = bindingManager.Scanner.FindPattern(options.FollowEntityPattern);
- if (!followEntityAddress.Found)
- {
- return new BindingNotFoundError(options.FollowEntityPattern, "CharacterBinding.FollowEntity");
- }
-
- var unfollowEntityAddress = bindingManager.Scanner.FindPattern(options.UnfollowEntityPattern);
- if (!unfollowEntityAddress.Found)
- {
- return new BindingNotFoundError(options.UnfollowEntityPattern, "CharacterBinding.UnfollowEntity");
- }
-
- var walkFunction = bindingManager.Hooks.CreateFunction<WalkDelegate>
- (walkFunctionAddress.Offset + (int)process.MainModule!.BaseAddress);
- var walkWrapper = walkFunction.GetWrapper();
-
- var followEntityFunction = bindingManager.Hooks.CreateFunction<FollowEntityDelegate>
- (followEntityAddress.Offset + (int)process.MainModule!.BaseAddress);
- var followEntityWrapper = followEntityFunction.GetWrapper();
-
- var unfollowEntityFunction = bindingManager.Hooks.CreateFunction<UnfollowEntityDelegate>
- (unfollowEntityAddress.Offset + (int)process.MainModule!.BaseAddress);
- var unfollowEntityWrapper = unfollowEntityFunction.GetWrapper();
-
var binding = new PlayerManagerBinding
(
bindingManager,
- playerManager,
- walkWrapper,
- followEntityWrapper,
- unfollowEntityWrapper
+ playerManager
);
- if (options.HookWalk)
+ var walkHookResult = bindingManager.CreateHookFromPattern<WalkDelegate>
+ ("CharacterBinding.Walk", binding.WalkDetour, options.WalkHook);
+ if (!walkHookResult.IsDefined(out var walkHook))
{
- binding._walkHook = walkFunction
- .Hook(binding.WalkDetour);
- binding._originalWalk = binding._walkHook.OriginalFunction;
+ return Result<PlayerManagerBinding>.FromError(walkHookResult);
}
- if (options.HookFollowEntity)
+ var entityFollowHookResult = bindingManager.CreateHookFromPattern<FollowEntityDelegate>
+ ("CharacterBinding.EntityFollow", binding.FollowEntityDetour, options.EntityFollowHook);
+ if (!entityFollowHookResult.IsDefined(out var entityFollowHook))
{
- binding._followHook = followEntityFunction.Hook(binding.FollowEntityDetour);
- binding._originalFollowEntity = binding._followHook.OriginalFunction;
+ return Result<PlayerManagerBinding>.FromError(entityFollowHookResult);
}
- if (options.HookUnfollowEntity)
+ var entityUnfollowHookResult = bindingManager.CreateHookFromPattern<UnfollowEntityDelegate>
+ ("CharacterBinding.EntityUnfollow", binding.UnfollowEntityDetour, options.EntityUnfollowHook);
+ if (!entityUnfollowHookResult.IsDefined(out var entityUnfollowHook))
{
- binding._unfollowHook = unfollowEntityFunction.Hook(binding.UnfollowEntityDetour);
- binding._originalUnfollowEntity = binding._unfollowHook.OriginalFunction;
+ return Result<PlayerManagerBinding>.FromError(entityUnfollowHookResult);
}
- binding._walkHook?.Activate();
- binding._followHook?.Activate();
- binding._unfollowHook?.Activate();
+ binding._walkHook = walkHook;
+ binding._followHook = entityFollowHook;
+ binding._unfollowHook = entityUnfollowHook;
return binding;
}
private readonly NosBindingManager _bindingManager;
- private IHook<WalkDelegate>? _walkHook;
- private IHook<FollowEntityDelegate>? _followHook;
- private IHook<UnfollowEntityDelegate>? _unfollowHook;
-
- private FollowEntityDelegate _originalFollowEntity;
- private UnfollowEntityDelegate _originalUnfollowEntity;
- private WalkDelegate _originalWalk;
+ private IHook<WalkDelegate> _walkHook = null!;
+ private IHook<FollowEntityDelegate> _followHook = null!;
+ private IHook<UnfollowEntityDelegate> _unfollowHook = null!;
private PlayerManagerBinding
(
NosBindingManager bindingManager,
- PlayerManager playerManager,
- WalkDelegate originalWalk,
- FollowEntityDelegate originalFollowEntity,
- UnfollowEntityDelegate originalUnfollowEntity
+ PlayerManager playerManager
)
{
PlayerManager = playerManager;
_bindingManager = bindingManager;
- _originalWalk = originalWalk;
- _originalFollowEntity = originalFollowEntity;
- _originalUnfollowEntity = originalUnfollowEntity;
}
/// <summary>
@@ 195,7 152,7 @@ public class PlayerManagerBinding
int param = ((ushort)y << 16) | (ushort)x;
try
{
- return _originalWalk(PlayerManager.Address, param);
+ return _walkHook.OriginalFunction(PlayerManager.Address, param);
}
catch (Exception e)
{
@@ 208,7 165,7 @@ public class PlayerManagerBinding
var result = WalkCall?.Invoke((ushort)(position & 0xFFFF), (ushort)((position >> 16) & 0xFFFF));
if (result ?? true)
{
- return _originalWalk(characterObject, position, unknown0, unknown1);
+ return _walkHook.OriginalFunction(characterObject, position, unknown0, unknown1);
}
return false;
@@ 231,7 188,7 @@ public class PlayerManagerBinding
{
try
{
- _originalFollowEntity(PlayerManager.Address, entityAddress);
+ _followHook.OriginalFunction(PlayerManager.Address, entityAddress);
}
catch (Exception e)
{
@@ 249,7 206,7 @@ public class PlayerManagerBinding
{
try
{
- _originalUnfollowEntity(PlayerManager.Address);
+ _unfollowHook.OriginalFunction(PlayerManager.Address);
}
catch (Exception e)
{
@@ 270,7 227,7 @@ public class PlayerManagerBinding
var result = FollowEntityCall?.Invoke(new MapBaseObj(_bindingManager.Memory, entityPtr));
if (result ?? true)
{
- return _originalFollowEntity(playerManagerPtr, entityPtr, unknown1, unknown2);
+ return _followHook.OriginalFunction(playerManagerPtr, entityPtr, unknown1, unknown2);
}
return false;
@@ 281,7 238,7 @@ public class PlayerManagerBinding
var result = FollowEntityCall?.Invoke(null);
if (result ?? true)
{
- _originalUnfollowEntity(playerManagerPtr, unknown);
+ _unfollowHook.OriginalFunction(playerManagerPtr, unknown);
}
}
}=
\ No newline at end of file
M src/Core/NosSmooth.LocalBinding/Objects/UnitManagerBinding.cs => src/Core/NosSmooth.LocalBinding/Objects/UnitManagerBinding.cs +29 -25
@@ 31,7 31,7 @@ public class UnitManagerBinding
FunctionAttribute.StackCleanup.Callee,
new[] { FunctionAttribute.Register.ebx, FunctionAttribute.Register.esi, FunctionAttribute.Register.edi, FunctionAttribute.Register.ebp }
)]
- private delegate int FocusEntityDelegate(nuint unitManagerPtr, nuint entityPtr);
+ private delegate nuint FocusEntityDelegate(nuint unitManagerPtr, nuint entityPtr);
/// <summary>
/// Create the scene manager binding.
@@ 50,31 50,21 @@ public class UnitManagerBinding
return new BindingNotFoundError(bindingOptions.UnitManagerPattern, "UnitManagerBinding.UnitManager");
}
- var focusEntityAddress = bindingManager.Scanner.FindPattern(bindingOptions.FocusEntityPattern);
- if (!focusEntityAddress.Found)
- {
- return new BindingNotFoundError(bindingOptions.FocusEntityPattern, "UnitManagerBinding.FocusEntity");
- }
-
- var focusEntityFunction = bindingManager.Hooks.CreateFunction<FocusEntityDelegate>
- (focusEntityAddress.Offset + (int)process.MainModule!.BaseAddress + 0x04);
- var focusEntityWrapper = focusEntityFunction.GetWrapper();
-
var binding = new UnitManagerBinding
(
bindingManager,
(int)process.MainModule!.BaseAddress + unitManagerStaticAddress.Offset,
- bindingOptions.UnitManagerOffsets,
- focusEntityWrapper
+ bindingOptions.UnitManagerOffsets
);
- if (bindingOptions.HookFocusEntity)
+ var entityFocusHookResult = bindingManager.CreateHookFromPattern<FocusEntityDelegate>
+ ("UnitManager.EntityFocus", binding.FocusEntityDetour, bindingOptions.EntityFocusHook);
+ if (!entityFocusHookResult.IsDefined(out var entityFocusHook))
{
- binding._focusHook = focusEntityFunction.Hook(binding.FocusEntityDetour);
- binding._originalFocusEntity = binding._focusHook.OriginalFunction;
+ return Result<UnitManagerBinding>.FromError(entityFocusHookResult);
}
- binding._focusHook?.Activate();
+ binding._focusHook = entityFocusHook;
return binding;
}
@@ 82,19 72,16 @@ public class UnitManagerBinding
private readonly int[] _unitManagerOffsets;
private readonly NosBindingManager _bindingManager;
- private FocusEntityDelegate _originalFocusEntity;
- private IHook<FocusEntityDelegate>? _focusHook;
+ private IHook<FocusEntityDelegate> _focusHook = null!;
private UnitManagerBinding
(
NosBindingManager bindingManager,
int staticUnitManagerAddress,
- int[] unitManagerOffsets,
- FocusEntityDelegate originalFocusEntity
+ int[] unitManagerOffsets
)
{
- _originalFocusEntity = originalFocusEntity;
_bindingManager = bindingManager;
_staticUnitManagerAddress = staticUnitManagerAddress;
_unitManagerOffsets = unitManagerOffsets;
@@ 123,6 110,22 @@ public class UnitManagerBinding
=> FocusEntity(entity?.Address ?? nuint.Zero);
/// <summary>
+ /// Disable all UnitManager hooks.
+ /// </summary>
+ public void DisableHooks()
+ {
+ _focusHook.Disable();
+ }
+
+ /// <summary>
+ /// Enable all UnitManager hooks.
+ /// </summary>
+ public void EnableHooks()
+ {
+ _focusHook.Enable();
+ }
+
+ /// <summary>
/// Focus the entity.
/// </summary>
/// <param name="entityAddress">The entity address.</param>
@@ 131,7 134,7 @@ public class UnitManagerBinding
{
try
{
- _originalFocusEntity(Address, entityAddress);
+ _focusHook.OriginalFunction(Address, entityAddress);
}
catch (Exception e)
{
@@ 141,7 144,7 @@ public class UnitManagerBinding
return Result.FromSuccess();
}
- private int FocusEntityDetour(nuint unitManagerPtr, nuint entityId)
+ private nuint FocusEntityDetour(nuint unitManagerPtr, nuint entityId)
{
MapBaseObj? obj = null;
if (entityId != nuint.Zero)
@@ 150,9 153,10 @@ public class UnitManagerBinding
}
var result = EntityFocus?.Invoke(obj);
+
if (result ?? true)
{
- return _originalFocusEntity(unitManagerPtr, entityId);
+ return _focusHook.OriginalFunction(unitManagerPtr, entityId);
}
return 0;
M src/Core/NosSmooth.LocalBinding/Options/CharacterBindingOptions.cs => src/Core/NosSmooth.LocalBinding/Options/CharacterBindingOptions.cs +8 -23
@@ 14,34 14,19 @@ namespace NosSmooth.LocalBinding.Options;
public class CharacterBindingOptions
{
/// <summary>
- /// Gets or sets whether to hook the walk function.
+ /// Gets or sets the configuration for player walk function hook.
/// </summary>
- public bool HookWalk { get; set; } = true;
+ public HookOptions WalkHook { get; set; } = new HookOptions(false, "55 8B EC 83 C4 EC 53 56 57 66 89 4D FA", 0);
/// <summary>
- /// Gets or sets the pattern to find the walk function at.
+ /// Gets or sets the configuration for entity follow function hook.
/// </summary>
- public string WalkFunctionPattern { get; set; } = "55 8B EC 83 C4 EC 53 56 57 66 89 4D FA";
+ public HookOptions EntityFollowHook { get; set; }
+ = new HookOptions(false, "55 8B EC 51 53 56 57 88 4D FF 8B F2 8B F8", 0);
/// <summary>
- /// Gets or sets the pattern to find the follow entity method at.
+ /// Gets or sets the configuration for entity unfollow function hook.
/// </summary>
- public string FollowEntityPattern { get; set; }
- = "55 8B EC 51 53 56 57 88 4D FF 8B F2 8B F8";
-
- /// <summary>
- /// Gets or sets the pattern to find the unfollow entity method at.
- /// </summary>
- public string UnfollowEntityPattern { get; set; }
- = "80 78 14 00 74 1A";
-
- /// <summary>
- /// Gets or sets whether to hook the follow entity function.
- /// </summary>
- public bool HookFollowEntity { get; set; } = true;
-
- /// <summary>
- /// Gets or sets whether to hook the unfollow entity function.
- /// </summary>
- public bool HookUnfollowEntity { get; set; } = true;
+ public HookOptions EntityUnfollowHook { get; set; }
+ = new HookOptions(false, "80 78 14 00 74 1A", 0);
}=
\ No newline at end of file
M src/Core/NosSmooth.LocalBinding/Options/NetworkBindingOptions.cs => src/Core/NosSmooth.LocalBinding/Options/NetworkBindingOptions.cs +6 -14
@@ 14,14 14,16 @@ namespace NosSmooth.LocalBinding.Options;
public class NetworkBindingOptions
{
/// <summary>
- /// Gets or sets whether to hook the send packet function.
+ /// Gets or sets the configuration for packet receive function hook.
/// </summary>
- public bool HookSend { get; set; } = true;
+ public HookOptions PacketReceiveHook { get; set; }
+ = new HookOptions(true, "55 8B EC 83 C4 ?? 53 56 57 33 C9 89 4D ?? 89 4D ?? 89 55 ?? 8B D8 8B 45 ??", 0);
/// <summary>
- /// Gets or sets whether to hook the receive packet function.
+ /// Gets or sets the configuration for packet send function hook.
/// </summary>
- public bool HookReceive { get; set; } = true;
+ public HookOptions PacketSendHook { get; set; }
+ = new HookOptions(true, "53 56 8B F2 8B D8 EB 04", 0);
/// <summary>
/// Gets or sets the pattern to find the network object at.
@@ 31,14 33,4 @@ public class NetworkBindingOptions
/// </remarks>
public string NetworkObjectPattern { get; set; }
= "A1 ?? ?? ?? ?? 8B 00 BA ?? ?? ?? ?? E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? A1 ?? ?? ?? ?? 8B 00 8B 40 40";
-
- /// <summary>
- /// Gets or sets the pattern to find the send packet function at.
- /// </summary>
- public string SendFunctionPattern { get; set; } = "53 56 8B F2 8B D8 EB 04";
-
- /// <summary>
- /// Gets or sets the pattern to find the receive function at.
- /// </summary>
- public string ReceiveFunctionPattern { get; set; } = "55 8B EC 83 C4 ?? 53 56 57 33 C9 89 4D ?? 89 4D ?? 89 55 ?? 8B D8 8B 45 ??";
}=
\ No newline at end of file
M src/Core/NosSmooth.LocalBinding/Options/PetManagerBindingOptions.cs => src/Core/NosSmooth.LocalBinding/Options/PetManagerBindingOptions.cs +3 -8
@@ 14,13 14,8 @@ namespace NosSmooth.LocalBinding.Options;
public class PetManagerBindingOptions
{
/// <summary>
- /// Gets or sets the pattern of a pet walk function.
+ /// Gets or sets the configuration for pet walk function hook.
/// </summary>
- public string PetWalkPattern { get; set; }
- = "55 8b ec 83 c4 e4 53 56 57 8b f9 89 55 fc 8b d8 c6 45 fb 00";
-
- /// <summary>
- /// Gets or sets whether to hook the pet walk function.
- /// </summary>
- public bool HookPetWalk { get; set; } = true;
+ public HookOptions PetWalkHook { get; set; }
+ = new HookOptions(false, "55 8b ec 83 c4 e4 53 56 57 8b f9 89 55 fc 8b d8 c6 45 fb 00", 0);
}=
\ No newline at end of file
M src/Core/NosSmooth.LocalBinding/Options/UnitManagerBindingOptions.cs => src/Core/NosSmooth.LocalBinding/Options/UnitManagerBindingOptions.cs +3 -8
@@ 26,13 26,8 @@ public class UnitManagerBindingOptions
= { 1, 0 };
/// <summary>
- /// Gets or sets the pattern to find the focus entity method at.
+ /// Gets or sets the configuration for entity focus function hook.
/// </summary>
- public string FocusEntityPattern { get; set; }
- = "73 00 00 00 55 8b ec b9 05 00 00 00";
-
- /// <summary>
- /// Gets or sets whether to hook the Focus entity function.
- /// </summary>
- public bool HookFocusEntity { get; set; } = true;
+ public HookOptions EntityFocusHook { get; set; }
+ = new HookOptions(false, "73 00 00 00 55 8b ec b9 05 00 00 00", 4);
}=
\ No newline at end of file
M src/Samples/LowLevel/WalkCommands/Startup.cs => src/Samples/LowLevel/WalkCommands/Startup.cs +9 -0
@@ 13,6 13,7 @@ using NosSmooth.Data.NOSFiles;
using NosSmooth.Data.NOSFiles.Extensions;
using NosSmooth.Extensions.Pathfinding.Extensions;
using NosSmooth.LocalBinding;
+using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalClient;
using NosSmooth.LocalClient.Extensions;
using NosSmooth.Packets.Extensions;
@@ 31,6 32,14 @@ public class Startup
{
var collection = new ServiceCollection()
.AddLocalClient()
+
+ // hook pet and player walk to
+ // recognize user action's and
+ // disable walking in case user
+ // decides to walk.
+ .ConfigureHooks(h => h
+ .HookPetWalk()
+ .HookPlayerWalk())
.AddNostaleDataFiles()
.AddNostalePathfinding()
.AddScoped<Commands.WalkCommands>()