From 11b39ddc1f9e681e04354f144c4563f4f6ca87cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Sat, 22 Jan 2022 19:56:17 +0100 Subject: [PATCH] feat: add external memory nostale browser --- .../ExternalNosBrowser.cs | 101 +++++++++++++ .../Structs/MapPlayerObj.cs | 45 ++++++ .../Structs/PlayerManager.cs | 134 ++++++++++++++++++ .../Structs/SceneManager.cs | 27 ++++ 4 files changed, 307 insertions(+) create mode 100644 Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs create mode 100644 Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs create mode 100644 Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs diff --git a/Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs b/Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs new file mode 100644 index 0000000..aa1467e --- /dev/null +++ b/Local/NosSmooth.LocalBinding/ExternalNosBrowser.cs @@ -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; + +/// +/// Used for browsing a nostale process data. +/// +public class ExternalNosBrowser +{ + private readonly CharacterBindingOptions _characterOptions; + private readonly SceneManagerBindingOptions _sceneManagerOptions; + private PlayerManager? _playerManager; + private SceneManager? _sceneManager; + + /// + /// Initializes a new instance of the class. + /// + /// The process to browse. + /// The options for obtaining player manager. + /// The scene manager options. + public ExternalNosBrowser + ( + Process process, + CharacterBindingOptions characterOptions, + SceneManagerBindingOptions sceneManagerOptions + ) + { + _characterOptions = characterOptions; + _sceneManagerOptions = sceneManagerOptions; + Process = process; + Memory = new ExternalMemory(process); + Scanner = new Scanner(process, process.MainModule); + } + + /// + /// The NosTale process. + /// + public Process Process { get; } + + /// + /// Gets the memory scanner. + /// + internal Scanner Scanner { get; } + + /// + /// Gets the current process memory. + /// + internal IMemory Memory { get; } + + /// + /// Get the player manager. + /// + /// The player manager or an error. + public Result GetPlayerManager() + { + if (_playerManager is null) + { + var playerManagerResult = PlayerManager.Create(this, _characterOptions); + if (!playerManagerResult.IsSuccess) + { + return playerManagerResult; + } + + _playerManager = playerManagerResult.Entity; + } + + return _playerManager; + } + + /// + /// Get the player manager. + /// + /// The player manager or an error. + public Result 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 diff --git a/Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs b/Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs new file mode 100644 index 0000000..c4284a5 --- /dev/null +++ b/Local/NosSmooth.LocalBinding/Structs/MapPlayerObj.cs @@ -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; + +/// +/// NosTale Player object. +/// +public class MapPlayerObj : MapBaseObj +{ + private readonly IMemory _memory; + + /// + /// Initializes a new instance of the class. + /// + /// The memory. + /// The player object pointer. + public MapPlayerObj(IMemory memory, IntPtr mapObjPointer) + : base(memory, mapObjPointer) + { + _memory = memory; + } + + /// + /// Gets the name of the player. + /// + 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 diff --git a/Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs b/Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs new file mode 100644 index 0000000..df934b9 --- /dev/null +++ b/Local/NosSmooth.LocalBinding/Structs/PlayerManager.cs @@ -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; + +/// +/// NosTale player manager. +/// +public class PlayerManager +{ + /// + /// Create instance. + /// + /// The NosTale process browser. + /// The options. + /// The player manager or an error. + public static Result 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; + + /// + /// Initializes a new instance of the class. + /// + /// The memory. + /// The pointer to the beginning of the player manager structure. + public PlayerManager(IMemory memory, IntPtr playerManager) + { + _memory = memory; + Address = playerManager; + } + + /// + /// Gets the address to the player manager. + /// + public IntPtr Address { get; } + + /// + /// Gets the current player position x coordinate. + /// + public int X + { + get + { + _memory.SafeRead(Address + 0x4, out short x); + return x; + } + } + + /// + /// Gets the current player position x coordinate. + /// + public int Y + { + get + { + _memory.SafeRead(Address + 0x6, out short y); + return y; + } + } + + /// + /// Gets the target x coordinate the player is moving to. + /// + public int TargetX + { + get + { + _memory.SafeRead(Address + 0x8, out short targetX); + return targetX; + } + } + + /// + /// Gets the target y coordinate the player is moving to. + /// + public int TargetY + { + get + { + _memory.SafeRead(Address + 0xA, out short targetX); + return targetX; + } + } + + /// + /// Gets the player object. + /// + public MapPlayerObj Player + { + get + { + _memory.SafeRead(Address + 0x20, out int playerAddress); + return new MapPlayerObj(_memory, (IntPtr)playerAddress); + } + } + + /// + /// Gets the player id. + /// + public int PlayerId + { + get + { + _memory.SafeRead(Address + 0x24, out int playerId); + return playerId; + } + } +} \ No newline at end of file diff --git a/Local/NosSmooth.LocalBinding/Structs/SceneManager.cs b/Local/NosSmooth.LocalBinding/Structs/SceneManager.cs index 8a91074..a6c3e53 100644 --- a/Local/NosSmooth.LocalBinding/Structs/SceneManager.cs +++ b/Local/NosSmooth.LocalBinding/Structs/SceneManager.cs @@ -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; /// public class SceneManager { + /// + /// Create instance. + /// + /// The NosTale process browser. + /// The options. + /// The player manager or an error. + public static Result 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; -- 2.48.1