A Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs => Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs +101 -0
@@ 0,0 1,101 @@
+//
+// ExternalNosBrowser.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 Microsoft.Extensions.Options;
+using NosSmooth.LocalBinding.Options;
+using NosSmooth.LocalBinding.Structs;
+using Reloaded.Memory.Sigscan;
+using Reloaded.Memory.Sources;
+using Remora.Results;
+
+namespace NosSmooth.LocalBinding;
+
+/// <summary>
+/// Used for browsing a nostale process data.
+/// </summary>
+public class ExternalNosBrowser
+{
+ private readonly CharacterBindingOptions _characterOptions;
+ private readonly SceneManagerBindingOptions _sceneManagerOptions;
+ private PlayerManager? _playerManager;
+ private SceneManager? _sceneManager;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ExternalNosBrowser"/> class.
+ /// </summary>
+ /// <param name="process">The process to browse.</param>
+ /// <param name="characterOptions">The options for obtaining player manager.</param>
+ /// <param name="sceneManagerOptions">The scene manager options.</param>
+ public ExternalNosBrowser
+ (
+ Process process,
+ CharacterBindingOptions characterOptions,
+ SceneManagerBindingOptions sceneManagerOptions
+ )
+ {
+ _characterOptions = characterOptions;
+ _sceneManagerOptions = sceneManagerOptions;
+ Process = process;
+ Memory = new ExternalMemory(process);
+ Scanner = new Scanner(process, process.MainModule);
+ }
+
+ /// <summary>
+ /// The NosTale process.
+ /// </summary>
+ public Process Process { get; }
+
+ /// <summary>
+ /// Gets the memory scanner.
+ /// </summary>
+ internal Scanner Scanner { get; }
+
+ /// <summary>
+ /// Gets the current process memory.
+ /// </summary>
+ internal IMemory Memory { get; }
+
+ /// <summary>
+ /// Get the player manager.
+ /// </summary>
+ /// <returns>The player manager or an error.</returns>
+ public Result<PlayerManager> GetPlayerManager()
+ {
+ if (_playerManager is null)
+ {
+ var playerManagerResult = PlayerManager.Create(this, _characterOptions);
+ if (!playerManagerResult.IsSuccess)
+ {
+ return playerManagerResult;
+ }
+
+ _playerManager = playerManagerResult.Entity;
+ }
+
+ return _playerManager;
+ }
+
+ /// <summary>
+ /// Get the player manager.
+ /// </summary>
+ /// <returns>The player manager or an error.</returns>
+ public Result<SceneManager> GetSceneManager()
+ {
+ if (_sceneManager is null)
+ {
+ var sceneManagerResult = SceneManager.Create(this, _sceneManagerOptions);
+ if (!sceneManagerResult.IsSuccess)
+ {
+ return sceneManagerResult;
+ }
+
+ _sceneManager = sceneManagerResult.Entity;
+ }
+
+ return _sceneManager;
+ }
+}<
\ No newline at end of file
A Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs => Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs +45 -0
@@ 0,0 1,45 @@
+//
+// MapPlayerObj.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.Runtime.InteropServices;
+using System.Text;
+using Reloaded.Memory.Sources;
+
+namespace NosSmooth.LocalBinding.Structs;
+
+/// <summary>
+/// NosTale Player object.
+/// </summary>
+public class MapPlayerObj : MapBaseObj
+{
+ private readonly IMemory _memory;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MapPlayerObj"/> class.
+ /// </summary>
+ /// <param name="memory">The memory.</param>
+ /// <param name="mapObjPointer">The player object pointer.</param>
+ public MapPlayerObj(IMemory memory, IntPtr mapObjPointer)
+ : base(memory, mapObjPointer)
+ {
+ _memory = memory;
+ }
+
+ /// <summary>
+ /// Gets the name of the player.
+ /// </summary>
+ public string? Name
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x1EC, out int nameAddress);
+ _memory.SafeRead((IntPtr)nameAddress - 4, out int nameLength);
+ byte[] data = new byte[nameLength];
+ _memory.SafeReadRaw((IntPtr)nameAddress, out data, nameLength);
+ return Encoding.ASCII.GetString(data);
+ }
+ }
+}<
\ No newline at end of file
A Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs => Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs +134 -0
@@ 0,0 1,134 @@
+//
+// PlayerManager.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.Errors;
+using NosSmooth.LocalBinding.Options;
+using Reloaded.Memory.Sources;
+using Remora.Results;
+
+namespace NosSmooth.LocalBinding.Structs;
+
+/// <summary>
+/// NosTale player manager.
+/// </summary>
+public class PlayerManager
+{
+ /// <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<PlayerManager> Create(ExternalNosBrowser nosBrowser, CharacterBindingOptions options)
+ {
+ var characterObjectAddress = nosBrowser.Scanner.CompiledFindPattern(options.CharacterObjectPattern);
+ if (!characterObjectAddress.Found)
+ {
+ return new BindingNotFoundError(options.CharacterObjectPattern, "PlayerManager");
+ }
+
+ if (nosBrowser.Process.MainModule is null)
+ {
+ return new NotFoundError("Cannot find the main module of the target process.");
+ }
+
+ var ptrAddress = nosBrowser.Process.MainModule.BaseAddress + characterObjectAddress.Offset + 0x06;
+ nosBrowser.Memory.SafeRead(ptrAddress, out int address);
+ nosBrowser.Memory.SafeRead((IntPtr)address, out address);
+ return new PlayerManager(nosBrowser.Memory, (IntPtr)address);
+ }
+
+ private readonly IMemory _memory;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PlayerManager"/> class.
+ /// </summary>
+ /// <param name="memory">The memory.</param>
+ /// <param name="playerManager">The pointer to the beginning of the player manager structure.</param>
+ public PlayerManager(IMemory memory, IntPtr playerManager)
+ {
+ _memory = memory;
+ Address = playerManager;
+ }
+
+ /// <summary>
+ /// Gets the address to the player manager.
+ /// </summary>
+ public IntPtr Address { get; }
+
+ /// <summary>
+ /// Gets the current player position x coordinate.
+ /// </summary>
+ public int X
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x4, out short x);
+ return x;
+ }
+ }
+
+ /// <summary>
+ /// Gets the current player position x coordinate.
+ /// </summary>
+ public int Y
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x6, out short y);
+ return y;
+ }
+ }
+
+ /// <summary>
+ /// Gets the target x coordinate the player is moving to.
+ /// </summary>
+ public int TargetX
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x8, out short targetX);
+ return targetX;
+ }
+ }
+
+ /// <summary>
+ /// Gets the target y coordinate the player is moving to.
+ /// </summary>
+ public int TargetY
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0xA, out short targetX);
+ return targetX;
+ }
+ }
+
+ /// <summary>
+ /// Gets the player object.
+ /// </summary>
+ public MapPlayerObj Player
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x20, out int playerAddress);
+ return new MapPlayerObj(_memory, (IntPtr)playerAddress);
+ }
+ }
+
+ /// <summary>
+ /// Gets the player id.
+ /// </summary>
+ public int PlayerId
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x24, out int playerId);
+ return playerId;
+ }
+ }
+}<
\ No newline at end of file
M Local/NosSmooth.LocalBinding/Structs/SceneManager.cs => Local/NosSmooth.LocalBinding/Structs/SceneManager.cs +27 -0
@@ 4,7 4,10 @@
// 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;
@@ 13,6 16,30 @@ namespace NosSmooth.LocalBinding.Structs;
/// </summary>
public class SceneManager
{
+ /// <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<SceneManager> Create(ExternalNosBrowser nosBrowser, SceneManagerBindingOptions options)
+ {
+ var characterObjectAddress = nosBrowser.Scanner.CompiledFindPattern(options.SceneManagerObjectPattern);
+ if (!characterObjectAddress.Found)
+ {
+ return new BindingNotFoundError(options.SceneManagerObjectPattern, "SceneManager");
+ }
+
+ if (nosBrowser.Process.MainModule is null)
+ {
+ return new NotFoundError("Cannot find the main module of the target process.");
+ }
+
+ var ptrAddress = nosBrowser.Process.MainModule.BaseAddress + characterObjectAddress.Offset;
+ nosBrowser.Memory.SafeRead(ptrAddress, out ptrAddress);
+ return new SceneManager(nosBrowser.Memory, ptrAddress);
+ }
+
private readonly IMemory _memory;
private readonly IntPtr _sceneManager;