~ruther/NosSmooth

24f396f971487fee671dad63848a1862a6bcd0a5 — František Boháček 3 years ago 2d0fe0a
feat(localbinding): add pet manager mapping
M Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs => Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs +26 -1
@@ 21,8 21,10 @@ public class ExternalNosBrowser
{
    private readonly PlayerManagerOptions _playerManagerOptions;
    private readonly SceneManagerOptions _sceneManagerOptions;
    private readonly PetManagerOptions _petManagerOptions;
    private PlayerManager? _playerManager;
    private SceneManager? _sceneManager;
    private PetManagerList? _petManagerList;

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


@@ 30,15 32,18 @@ public class ExternalNosBrowser
    /// <param name="process">The process to browse.</param>
    /// <param name="playerManagerOptions">The options for obtaining player manager.</param>
    /// <param name="sceneManagerOptions">The scene manager options.</param>
    /// <param name="petManagerOptions">The pet manager options.</param>
    public ExternalNosBrowser
    (
        Process process,
        PlayerManagerOptions playerManagerOptions,
        SceneManagerOptions sceneManagerOptions
        SceneManagerOptions sceneManagerOptions,
        PetManagerOptions petManagerOptions
    )
    {
        _playerManagerOptions = playerManagerOptions;
        _sceneManagerOptions = sceneManagerOptions;
        _petManagerOptions = petManagerOptions;
        Process = process;
        Memory = new ExternalMemory(process);
        Scanner = new Scanner(process, process.MainModule);


@@ 98,4 103,24 @@ public class ExternalNosBrowser

        return _sceneManager;
    }

    /// <summary>
    /// Get the pet manager list.
    /// </summary>
    /// <returns>The player manager or an error.</returns>
    public Result<PetManagerList> GetPetManagerList()
    {
        if (_petManagerList is null)
        {
            var petManagerResult = PetManagerList.Create(this, _petManagerOptions);
            if (!petManagerResult.IsSuccess)
            {
                return petManagerResult;
            }

            _petManagerList = petManagerResult.Entity;
        }

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

M Local/NosSmooth.LocalBinding/NosBindingManager.cs => Local/NosSmooth.LocalBinding/NosBindingManager.cs +9 -2
@@ 38,13 38,15 @@ public class NosBindingManager : IDisposable
    /// <param name="sceneManagerBindingOptions">The scene manager binding options.</param>
    /// <param name="playerManagerOptions">The player manager options.</param>
    /// <param name="sceneManagerOptions">The scene manager options.</param>
    /// <param name="petManagerOptions">The pet manager options.</param>
    public NosBindingManager
    (
        IOptions<CharacterBindingOptions> characterBindingOptions,
        IOptions<NetworkBindingOptions> networkBindingOptions,
        IOptions<SceneManagerBindingOptions> sceneManagerBindingOptions,
        IOptions<PlayerManagerOptions> playerManagerOptions,
        IOptions<SceneManagerOptions> sceneManagerOptions
        IOptions<SceneManagerOptions> sceneManagerOptions,
        IOptions<PetManagerOptions> petManagerOptions
    )
    {
        Hooks = new ReloadedHooks();


@@ 54,7 56,12 @@ public class NosBindingManager : IDisposable
        _networkBindingOptions = networkBindingOptions.Value;
        _sceneManagerBindingOptions = sceneManagerBindingOptions.Value;
        _nosBrowser = new ExternalNosBrowser
            (Process.GetCurrentProcess(), playerManagerOptions.Value, sceneManagerOptions.Value);
        (
            Process.GetCurrentProcess(),
            playerManagerOptions.Value,
            sceneManagerOptions.Value,
            petManagerOptions.Value
        );
    }

    /// <summary>

A Local/NosSmooth.LocalBinding/Options/PetManagerOptions.cs => Local/NosSmooth.LocalBinding/Options/PetManagerOptions.cs +27 -0
@@ 0,0 1,27 @@
//
//  PetManagerOptions.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.Objects;

namespace NosSmooth.LocalBinding.Options;

/// <summary>
/// Options for <see cref="PetManagerBinding"/>.
/// </summary>
public class PetManagerOptions
{
    /// <summary>
    /// Gets or sets the pattern to find static pet manager list address at.
    /// </summary>
    public string PetManagerListPattern { get; set; }
        = "00 ff 70 00 ?? ?? ?? ?? 10 90";

    /// <summary>
    /// Gets or sets the offsets to find the pet manager list at from the static address.
    /// </summary>
    public int[] PetManagerListOffsets { get; set; }
        = { 4, 8, 0x180, 0x18, 0x1C, 0x54 };
}
\ No newline at end of file

A Local/NosSmooth.LocalBinding/Structs/MapNpcObj.cs => Local/NosSmooth.LocalBinding/Structs/MapNpcObj.cs +25 -0
@@ 0,0 1,25 @@
//
//  MapNpcObj.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 Reloaded.Memory.Sources;

namespace NosSmooth.LocalBinding.Structs;

/// <summary>
/// Npc NosTale object.
/// </summary>
public class MapNpcObj : MapBaseObj
{
    /// <summary>
    /// Initializes a new instance of the <see cref="MapNpcObj"/> class.
    /// </summary>
    /// <param name="memory">The memory.</param>
    /// <param name="mapObjPointer">The pointer to the object.</param>
    public MapNpcObj(IMemory memory, IntPtr mapObjPointer)
        : base(memory, mapObjPointer)
    {
    }
}
\ No newline at end of file

A Local/NosSmooth.LocalBinding/Structs/PetManager.cs => Local/NosSmooth.LocalBinding/Structs/PetManager.cs +49 -0
@@ 0,0 1,49 @@
//
//  PetManager.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.Errors;
using NosSmooth.LocalBinding.Options;
using Reloaded.Memory.Sources;
using Remora.Results;

namespace NosSmooth.LocalBinding.Structs;

/// <summary>
/// NosTale pet manager.
/// </summary>
public class PetManager : ControlManager
{
    private readonly IMemory _memory;

    /// <summary>
    /// Initializes a new instance of the <see cref="PetManager"/> class.
    /// </summary>
    /// <param name="memory">The memory.</param>
    /// <param name="petManagerAddress">The pet manager address.</param>
    public PetManager(IMemory memory, IntPtr petManagerAddress)
        : base(memory)
    {
        _memory = memory;
        Address = petManagerAddress;
    }

    /// <summary>
    /// Gets the address of the pet manager.
    /// </summary>
    public override IntPtr Address { get; }

    /// <summary>
    /// Gets the player object.
    /// </summary>
    public MapNpcObj Pet
    {
        get
        {
            _memory.SafeRead(Address + 0x20, out int playerAddress);
            return new MapNpcObj(_memory, (IntPtr)playerAddress);
        }
    }
}
\ No newline at end of file

A Local/NosSmooth.LocalBinding/Structs/PetManagerList.cs => Local/NosSmooth.LocalBinding/Structs/PetManagerList.cs +116 -0
@@ 0,0 1,116 @@
//
//  PetManagerList.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.Errors;
using NosSmooth.LocalBinding.Extensions;
using NosSmooth.LocalBinding.Options;
using Reloaded.Memory.Sources;
using Remora.Results;

namespace NosSmooth.LocalBinding.Structs;

/// <summary>
/// NosTale list of <see cref="PetManager"/>.
/// </summary>
public class PetManagerList
{
    /// <summary>
    /// Create <see cref="PlayerManager"/> instance.
    /// </summary>
    /// <param name="nosBrowser">The NosTale process browser.</param>
    /// <param name="options">The options.</param>
    /// <returns>The player manager or an error.</returns>
    public static Result<PetManagerList> Create(ExternalNosBrowser nosBrowser, PetManagerOptions options)
    {
        var characterObjectAddress = nosBrowser.Scanner.CompiledFindPattern(options.PetManagerListPattern);
        if (!characterObjectAddress.Found)
        {
            return new BindingNotFoundError(options.PetManagerListPattern, "PetManagerList");
        }

        if (nosBrowser.Process.MainModule is null)
        {
            return new NotFoundError("Cannot find the main module of the target process.");
        }

        int staticManagerAddress = (int)nosBrowser.Process.MainModule.BaseAddress + characterObjectAddress.Offset;
        return new PetManagerList(nosBrowser.Memory, staticManagerAddress, options.PetManagerListOffsets);
    }

    private readonly IMemory _memory;
    private readonly int _staticPetManagerListAddress;
    private readonly int[] _staticPetManagerOffsets;

    /// <summary>
    /// Initializes a new instance of the <see cref="PetManagerList"/> class.
    /// </summary>
    /// <param name="memory">The memory.</param>
    /// <param name="staticPetManagerListAddress">The static pet manager address.</param>
    /// <param name="staticPetManagerOffsets">The offsets to follow to the pet manager list address.</param>
    public PetManagerList(IMemory memory, int staticPetManagerListAddress, int[] staticPetManagerOffsets)
    {
        _memory = memory;
        _staticPetManagerListAddress = staticPetManagerListAddress;
        _staticPetManagerOffsets = staticPetManagerOffsets;
    }

    /// <summary>
    /// Gets the address of the pet manager.
    /// </summary>
    /// <returns>An address to the pet manager list.</returns>
    public IntPtr Address => _memory.FollowStaticAddressOffsets(_staticPetManagerListAddress, _staticPetManagerOffsets);

    /// <summary>
    /// Gets the length of the array.
    /// </summary>
    public int Length
    {
        get
        {
            _memory.SafeRead(Address + 0x08, out int length);
            return length;
        }
    }

    private IntPtr List
    {
        get
        {
            _memory.SafeRead(Address + 0x04, out int listPointer);
            return (IntPtr)listPointer;
        }
    }

    /// <summary>
    /// Get the first pet.
    /// </summary>
    /// <returns>First pet, if exists.</returns>
    public MapNpcObj? GetFirst()
    {
        if (Length == 0)
        {
            return null;
        }

        _memory.SafeRead(List, out int firstAddress);
        return new MapNpcObj(_memory, (IntPtr)firstAddress);
    }

    /// <summary>
    /// Get the second pet.
    /// </summary>
    /// <returns>Second pet, if exists.</returns>
    public MapNpcObj? GetSecond()
    {
        if (Length < 2)
        {
            return null;
        }

        _memory.SafeRead(List + 0x04, out int secondAddress);
        return new MapNpcObj(_memory, (IntPtr)secondAddress);
    }
}
\ No newline at end of file

M Local/NosSmooth.LocalBinding/Structs/SceneManager.cs => Local/NosSmooth.LocalBinding/Structs/SceneManager.cs +1 -1
@@ 36,7 36,7 @@ public class SceneManager
            return new NotFoundError("Cannot find the main module of the target process.");
        }

        int staticManagerAddress = (int)nosBrowser.Process.MainModule.BaseAddress + characterObjectAddress.Offset + 1;
        int staticManagerAddress = (int)nosBrowser.Process.MainModule.BaseAddress + characterObjectAddress.Offset;
        return new SceneManager(nosBrowser.Memory, staticManagerAddress, options.SceneManagerOffsets);
    }


Do not follow this link