~ruther/NosSmooth

07aa0c3ff886a320f3755df66bd172214c972371 — Rutherther 3 years ago 8715225
fix: move focus function to unit manager
5 files changed, 129 insertions(+), 104 deletions(-)

M Local/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs
M Local/NosSmooth.LocalBinding/NosBindingManager.cs
R Local/NosSmooth.LocalBinding/Objects/{SceneManagerBinding.cs => UnitManagerBinding.cs}
R Local/NosSmooth.LocalBinding/Options/{SceneManagerBindingOptions.cs => UnitManagerBindingOptions.cs}
M Local/NosSmooth.LocalBinding/Structs/SceneManager.cs
M Local/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs => Local/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs +2 -1
@@ 29,8 29,9 @@ public static class ServiceCollectionExtensions
    {
        return serviceCollection
            .AddSingleton<NosBindingManager>()
            .AddSingleton(p => p.GetRequiredService<NosBindingManager>().NosBrowser)
            .AddSingleton(p => p.GetRequiredService<NosBindingManager>().PlayerManager)
            .AddSingleton(p => p.GetRequiredService<NosBindingManager>().SceneManager)
            .AddSingleton(p => p.GetRequiredService<NosBindingManager>().UnitManager)
            .AddSingleton(p => p.GetRequiredService<NosBindingManager>().Network);
    }
}
\ No newline at end of file

M Local/NosSmooth.LocalBinding/NosBindingManager.cs => Local/NosSmooth.LocalBinding/NosBindingManager.cs +19 -22
@@ 23,12 23,11 @@ public class NosBindingManager : IDisposable
{
    private readonly CharacterBindingOptions _characterBindingOptions;
    private readonly NetworkBindingOptions _networkBindingOptions;
    private readonly ExternalNosBrowser _nosBrowser;
    private SceneManagerBindingOptions _sceneManagerBindingOptions;
    private UnitManagerBindingOptions _unitManagerBindingOptions;

    private NetworkBinding? _networkBinding;
    private PlayerManagerBinding? _characterBinding;
    private SceneManagerBinding? _sceneManagerBinding;
    private UnitManagerBinding? _unitManagerBinding;

    /// <summary>
    /// Initializes a new instance of the <see cref="NosBindingManager"/> class.


@@ 43,7 42,7 @@ public class NosBindingManager : IDisposable
    (
        IOptions<CharacterBindingOptions> characterBindingOptions,
        IOptions<NetworkBindingOptions> networkBindingOptions,
        IOptions<SceneManagerBindingOptions> sceneManagerBindingOptions,
        IOptions<UnitManagerBindingOptions> sceneManagerBindingOptions,
        IOptions<PlayerManagerOptions> playerManagerOptions,
        IOptions<SceneManagerOptions> sceneManagerOptions,
        IOptions<PetManagerOptions> petManagerOptions


@@ 54,8 53,8 @@ public class NosBindingManager : IDisposable
        Scanner = new Scanner(Process.GetCurrentProcess(), Process.GetCurrentProcess().MainModule);
        _characterBindingOptions = characterBindingOptions.Value;
        _networkBindingOptions = networkBindingOptions.Value;
        _sceneManagerBindingOptions = sceneManagerBindingOptions.Value;
        _nosBrowser = new ExternalNosBrowser
        _unitManagerBindingOptions = sceneManagerBindingOptions.Value;
        NosBrowser = new ExternalNosBrowser
        (
            Process.GetCurrentProcess(),
            playerManagerOptions.Value,


@@ 65,6 64,11 @@ public class NosBindingManager : IDisposable
    }

    /// <summary>
    /// Gets the nos browser.
    /// </summary>
    public ExternalNosBrowser NosBrowser { get; }

    /// <summary>
    /// Gets the memory scanner.
    /// </summary>
    internal Scanner Scanner { get; }


@@ 123,11 127,11 @@ public class NosBindingManager : IDisposable
    /// Gets the character binding.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if the manager is not initialized yet.</exception>
    public SceneManagerBinding SceneManager
    public UnitManagerBinding UnitManager
    {
        get
        {
            if (_sceneManagerBinding is null)
            if (_unitManagerBinding is null)
            {
                throw new InvalidOperationException
                (


@@ 135,7 139,7 @@ public class NosBindingManager : IDisposable
                );
            }

            return _sceneManagerBinding;
            return _unitManagerBinding;
        }
    }



@@ 152,18 156,12 @@ public class NosBindingManager : IDisposable
        }
        _networkBinding = network.Entity;

        var playerManager = _nosBrowser.GetPlayerManager();
        var playerManager = NosBrowser.GetPlayerManager();
        if (!playerManager.IsSuccess)
        {
            return Result.FromError(playerManager);
        }

        var sceneManager = _nosBrowser.GetSceneManager();
        if (!sceneManager.IsSuccess)
        {
            return Result.FromError(sceneManager);
        }

        var playerManagerBinding = PlayerManagerBinding.Create
        (
            this,


@@ 176,17 174,16 @@ public class NosBindingManager : IDisposable
        }
        _characterBinding = playerManagerBinding.Entity;

        var sceneManagerBinding = SceneManagerBinding.Create
        var unitManagerBinding = UnitManagerBinding.Create
        (
            this,
            sceneManager.Entity,
            _sceneManagerBindingOptions
            _unitManagerBindingOptions
        );
        if (!sceneManagerBinding.IsSuccess)
        if (!unitManagerBinding.IsSuccess)
        {
            return Result.FromError(sceneManagerBinding);
            return Result.FromError(unitManagerBinding);
        }
        _sceneManagerBinding = sceneManagerBinding.Entity;
        _unitManagerBinding = unitManagerBinding.Entity;

        return Result.FromSuccess();
    }

R Local/NosSmooth.LocalBinding/Objects/SceneManagerBinding.cs => Local/NosSmooth.LocalBinding/Objects/UnitManagerBinding.cs +40 -78
@@ 1,11 1,12 @@
//
//  SceneManagerBinding.cs
//  UnitManagerBinding.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.Diagnostics;
using NosSmooth.LocalBinding.Errors;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using NosSmooth.LocalBinding.Structs;
using Reloaded.Hooks;


@@ 13,6 14,7 @@ using Reloaded.Hooks.Definitions;
using Reloaded.Hooks.Definitions.X86;
using Reloaded.Memory.Buffers.Internal.Kernel32;
using Remora.Results;
using SharpDisasm.Udis86;

namespace NosSmooth.LocalBinding.Objects;



@@ 22,42 24,48 @@ namespace NosSmooth.LocalBinding.Objects;
/// <remarks>
/// The scene manager holds addresses to entities, mouse position, ....
/// </remarks>
public class SceneManagerBinding
public class UnitManagerBinding
{
    [Function
    (
        new[] { FunctionAttribute.Register.eax, FunctionAttribute.Register.edx },
        FunctionAttribute.Register.ecx,
        FunctionAttribute.Register.eax,
        FunctionAttribute.StackCleanup.Callee
    )]
    private delegate void FocusEntityDelegate(IntPtr outputStringPtr, IntPtr entityPtr);
    private delegate int FocusEntityDelegate(IntPtr unitManagerPtr, IntPtr entityPtr);

    /// <summary>
    /// Create the scene manager binding.
    /// </summary>
    /// <param name="bindingManager">The binding manager.</param>
    /// <param name="sceneManager">The scene manager.</param>
    /// <param name="bindingOptions">The options for the binding.</param>
    /// <returns>A network binding or an error.</returns>
    public static Result<SceneManagerBinding> Create
        (NosBindingManager bindingManager, SceneManager sceneManager, SceneManagerBindingOptions bindingOptions)
    public static Result<UnitManagerBinding> Create
        (NosBindingManager bindingManager, UnitManagerBindingOptions bindingOptions)
    {
        var process = Process.GetCurrentProcess();

        var unitManagerStaticAddress = bindingManager.Scanner.CompiledFindPattern(bindingOptions.UnitManagerPattern);
        if (!unitManagerStaticAddress.Found)
        {
            return new BindingNotFoundError(bindingOptions.UnitManagerPattern, "UnitManagerBinding.UnitManager");
        }

        var focusEntityAddress = bindingManager.Scanner.CompiledFindPattern(bindingOptions.FocusEntityPattern);
        if (!focusEntityAddress.Found)
        {
            return new BindingNotFoundError(bindingOptions.FocusEntityPattern, "SceneManagerBinding.FocusEntity");
            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 SceneManagerBinding
        var binding = new UnitManagerBinding
        (
            bindingManager,
            sceneManager,
            (int)process.MainModule!.BaseAddress + unitManagerStaticAddress.Offset,
            bindingOptions.UnitManagerOffsets,
            focusEntityWrapper
        );



@@ 71,24 79,35 @@ public class SceneManagerBinding
        return binding;
    }

    private readonly int _staticUnitManagerAddress;
    private readonly int[] _unitManagerOffsets;

    private readonly NosBindingManager _bindingManager;
    private FocusEntityDelegate _originalFocusEntity;

    private IHook<FocusEntityDelegate>? _focusHook;

    private SceneManagerBinding
    private UnitManagerBinding
    (
        NosBindingManager bindingManager,
        SceneManager sceneManager,
        int staticUnitManagerAddress,
        int[] unitManagerOffsets,
        FocusEntityDelegate originalFocusEntity
    )
    {
        _originalFocusEntity = originalFocusEntity;
        _bindingManager = bindingManager;
        SceneManager = sceneManager;
        _staticUnitManagerAddress = staticUnitManagerAddress;
        _unitManagerOffsets = unitManagerOffsets;
    }

    /// <summary>
    /// Gets the address of unit manager.
    /// </summary>
    public IntPtr Address => _bindingManager.Memory.FollowStaticAddressOffsets
        (_staticUnitManagerAddress, _unitManagerOffsets);

    /// <summary>
    /// Event that is called when entity focus was called by NosTale.
    /// </summary>
    /// <remarks>


@@ 97,27 116,6 @@ public class SceneManagerBinding
    public event Func<MapBaseObj?, bool>? EntityFocus;

    /// <summary>
    /// Gets the scene manager object.
    /// </summary>
    public SceneManager SceneManager { get; }

    /// <summary>
    /// Focus the entity with the given id.
    /// </summary>
    /// <param name="id">The id of the entity.</param>
    /// <returns>A result that may or may not have succeeded.</returns>
    public Result FocusEntity(int id)
    {
        var entityResult = FindEntity(id);
        if (!entityResult.IsSuccess)
        {
            return Result.FromError(entityResult);
        }

        return FocusEntity(entityResult.Entity);
    }

    /// <summary>
    /// Focus the entity.
    /// </summary>
    /// <param name="entity">The entity.</param>


@@ 134,7 132,8 @@ public class SceneManagerBinding
    {
        try
        {
            _originalFocusEntity(IntPtr.Zero, entityAddress);
            var res = _originalFocusEntity(Address, entityAddress);
            Console.WriteLine(res);
        }
        catch (Exception e)
        {


@@ 144,48 143,7 @@ public class SceneManagerBinding
        return Result.FromSuccess();
    }

    /// <summary>
    /// Find the given entity address.
    /// </summary>
    /// <param name="id">The id of the entity.</param>
    /// <returns>The pointer to the entity or an error.</returns>
    public Result<MapBaseObj?> FindEntity(int id)
    {
        if (id == 0)
        {
            return Result<MapBaseObj?>.FromSuccess(null);
        }

        var manager = SceneManager;

        var item = manager.ItemList.FirstOrDefault(x => x.Id == id);
        if (item is not null)
        {
            return item;
        }

        var monster = manager.MonsterList.FirstOrDefault(x => x.Id == id);
        if (monster is not null)
        {
            return monster;
        }

        var npc = manager.NpcList.FirstOrDefault(x => x.Id == id);
        if (npc is not null)
        {
            return npc;
        }

        var player = manager.PlayerList.FirstOrDefault(x => x.Id == id);
        if (player is not null)
        {
            return player;
        }

        return new NotFoundError($"Could not find entity with id {id}");
    }

    private void FocusEntityDetour(IntPtr outputStringPtr, IntPtr entityId)
    private int FocusEntityDetour(IntPtr unitManagerPtr, IntPtr entityId)
    {
        MapBaseObj? obj = null;
        if (entityId != IntPtr.Zero)


@@ 196,7 154,11 @@ public class SceneManagerBinding
        var result = EntityFocus?.Invoke(obj);
        if (result ?? true)
        {
            _originalFocusEntity(outputStringPtr, entityId);
            var res = _originalFocusEntity(unitManagerPtr, entityId);
            Console.WriteLine(res);
            return res;
        }

        return 0;
    }
}
\ No newline at end of file

R Local/NosSmooth.LocalBinding/Options/SceneManagerBindingOptions.cs => Local/NosSmooth.LocalBinding/Options/UnitManagerBindingOptions.cs +15 -3
@@ 1,5 1,5 @@
//
//  SceneManagerBindingOptions.cs
//  UnitManagerBindingOptions.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.


@@ 9,11 9,23 @@ using NosSmooth.LocalBinding.Objects;
namespace NosSmooth.LocalBinding.Options;

/// <summary>
/// Options for <see cref="SceneManagerBinding"/>.
/// Options for <see cref="UnitManagerBinding"/>.
/// </summary>
public class SceneManagerBindingOptions
public class UnitManagerBindingOptions
{
    /// <summary>
    /// Gets or sets the pattern to static address of unit manager.
    /// </summary>
    public string UnitManagerPattern { get; set; }
        = "TODO";

    /// <summary>
    /// Gets or sets the pointer offsets from the unit manager static address.
    /// </summary>
    public int[] UnitManagerOffsets { get; set; }
        = { 15 };

    /// <summary>
    /// Gets or sets the pattern to find the focus entity method at.
    /// </summary>
    public string FocusEntityPattern { get; set; }

M Local/NosSmooth.LocalBinding/Structs/SceneManager.cs => Local/NosSmooth.LocalBinding/Structs/SceneManager.cs +53 -0
@@ 99,9 99,62 @@ public class SceneManager
        }
    }

    /// <summary>
    /// Gets the lock on target marked address.
    /// </summary>
    public IntPtr LockOnTargetMarkedAddress
    {
        get
        {
            var ptr = ReadPtr(Address + 0x1C);
            ptr = ReadPtr(ptr + 0x04);
            ptr = ReadPtr(ptr + 0x00);
            return ptr;
        }
    }

    private IntPtr ReadPtr(IntPtr ptr)
    {
        _memory.Read(ptr, out int read);
        return (IntPtr)read;
    }

    /// <summary>
    /// Find the given entity address.
    /// </summary>
    /// <param name="id">The id of the entity.</param>
    /// <returns>The pointer to the entity or an error.</returns>
    public Result<MapBaseObj?> FindEntity(int id)
    {
        if (id == 0)
        {
            return Result<MapBaseObj?>.FromSuccess(null);
        }

        var item = ItemList.FirstOrDefault(x => x.Id == id);
        if (item is not null)
        {
            return item;
        }

        var monster = MonsterList.FirstOrDefault(x => x.Id == id);
        if (monster is not null)
        {
            return monster;
        }

        var npc = NpcList.FirstOrDefault(x => x.Id == id);
        if (npc is not null)
        {
            return npc;
        }

        var player = PlayerList.FirstOrDefault(x => x.Id == id);
        if (player is not null)
        {
            return player;
        }

        return new NotFoundError($"Could not find entity with id {id}");
    }
}
\ No newline at end of file

Do not follow this link