M src/Core/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs => src/Core/NosSmooth.LocalBinding/Extensions/ServiceCollectionExtensions.cs +1 -0
@@ 53,6 53,7 @@ public static class ServiceCollectionExtensions
.AddSingleton(p => p.GetRequiredService<NosBrowserManager>().PlayerManager)
.AddSingleton(p => p.GetRequiredService<NosBrowserManager>().NetworkManager)
.AddSingleton(p => p.GetRequiredService<NosBrowserManager>().UnitManager)
+ .AddSingleton(p => p.GetRequiredService<NosBrowserManager>().NtClient)
.AddSingleton(p => p.GetRequiredService<IHookManager>().PacketReceive)
.AddSingleton(p => p.GetRequiredService<IHookManager>().PacketSend)
.AddSingleton(p => p.GetRequiredService<IHookManager>().PlayerWalk)
M src/Core/NosSmooth.LocalBinding/Hooks/Implementations/HookManager.cs => src/Core/NosSmooth.LocalBinding/Hooks/Implementations/HookManager.cs +1 -1
@@ 21,7 21,7 @@ internal class HookManager : IHookManager
/// Initializes a new instance of the <see cref="HookManager"/> class.
/// </summary>
/// <param name="options">The hook manager options.</param>
- public HookManager(IOptions<HookManagerOptions> options)
+ public HookManager(IOptionsSnapshot<HookManagerOptions> options)
{
_options = options.Value;
_hooks = new Dictionary<string, INostaleHook>();
M src/Core/NosSmooth.LocalBinding/NosBrowserManager.cs => src/Core/NosSmooth.LocalBinding/NosBrowserManager.cs +53 -7
@@ 58,11 58,13 @@ public class NosBrowserManager
private readonly PetManagerOptions _petManagerOptions;
private readonly NetworkManagerOptions _networkManagerOptions;
private readonly UnitManagerOptions _unitManagerOptions;
+ private readonly NtClientOptions _ntClientOptions;
private PlayerManager? _playerManager;
private SceneManager? _sceneManager;
private PetManagerList? _petManagerList;
private NetworkManager? _networkManager;
private UnitManager? _unitManager;
+ private NtClient? _ntClient;
/// <summary>
/// Initializes a new instance of the <see cref="NosBrowserManager"/> class.
@@ 72,13 74,15 @@ public class NosBrowserManager
/// <param name="petManagerOptions">The pet manager options.</param>
/// <param name="networkManagerOptions">The network manager options.</param>
/// <param name="unitManagerOptions">The unit manager options.</param>
+ /// <param name="ntClientOptions">The nt client options.</param>
public NosBrowserManager
(
- IOptions<PlayerManagerOptions> playerManagerOptions,
- IOptions<SceneManagerOptions> sceneManagerOptions,
- IOptions<PetManagerOptions> petManagerOptions,
- IOptions<NetworkManagerOptions> networkManagerOptions,
- IOptions<UnitManagerOptions> unitManagerOptions
+ IOptionsSnapshot<PlayerManagerOptions> playerManagerOptions,
+ IOptionsSnapshot<SceneManagerOptions> sceneManagerOptions,
+ IOptionsSnapshot<PetManagerOptions> petManagerOptions,
+ IOptionsSnapshot<NetworkManagerOptions> networkManagerOptions,
+ IOptionsSnapshot<UnitManagerOptions> unitManagerOptions,
+ IOptionsSnapshot<NtClientOptions> ntClientOptions
)
: this
(
@@ 87,7 91,8 @@ public class NosBrowserManager
sceneManagerOptions.Value,
petManagerOptions.Value,
networkManagerOptions.Value,
- unitManagerOptions.Value
+ unitManagerOptions.Value,
+ ntClientOptions.Value
)
{
}
@@ 101,6 106,7 @@ public class NosBrowserManager
/// <param name="petManagerOptions">The pet manager options.</param>
/// <param name="networkManagerOptions">The network manager options.</param>
/// <param name="unitManagerOptions">The unit manager options.</param>
+ /// <param name="ntClientOptions">The nt client options.</param>
public NosBrowserManager
(
Process process,
@@ 108,7 114,8 @@ public class NosBrowserManager
SceneManagerOptions sceneManagerOptions,
PetManagerOptions petManagerOptions,
NetworkManagerOptions networkManagerOptions,
- UnitManagerOptions unitManagerOptions
+ UnitManagerOptions unitManagerOptions,
+ NtClientOptions ntClientOptions
)
{
_playerManagerOptions = playerManagerOptions;
@@ 116,6 123,7 @@ public class NosBrowserManager
_petManagerOptions = petManagerOptions;
_networkManagerOptions = networkManagerOptions;
_unitManagerOptions = unitManagerOptions;
+ _ntClientOptions = ntClientOptions;
Process = process;
Memory = Process.Id == Process.GetCurrentProcess().Id ? new Memory() : new ExternalMemory(process);
Scanner = new Scanner(process, process.MainModule);
@@ 197,6 205,26 @@ public class NosBrowserManager
}
/// <summary>
+ /// Gets the nt client.
+ /// </summary>
+ /// <exception cref="InvalidOperationException">Thrown if the browser is not initialized or there was an error with initialization of nt client.</exception>
+ public NtClient NtClient
+ {
+ get
+ {
+ if (_ntClient is null)
+ {
+ throw new InvalidOperationException
+ (
+ "Could not get nt client. The browser manager is not initialized. Did you forget to call NosBrowserManager.Initialize?"
+ );
+ }
+
+ return _ntClient;
+ }
+ }
+
+ /// <summary>
/// Gets the player manager.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown if the browser is not initialized or there was an error with initialization of player manager.</exception>
@@ 361,6 389,24 @@ public class NosBrowserManager
_petManagerList = petManagerResult.Entity;
}
+ if (_ntClient is null)
+ {
+ var ntClientResult = NtClient.Create(this, _ntClientOptions);
+ if (!ntClientResult.IsSuccess)
+ {
+ errorResults.Add
+ (
+ Result.FromError
+ (
+ new CouldNotInitializeModuleError(typeof(NtClient), ntClientResult.Error),
+ ntClientResult
+ )
+ );
+ }
+
+ _ntClient = ntClientResult.Entity;
+ }
+
return errorResults.Count switch
{
0 => Result.FromSuccess(),
A src/Core/NosSmooth.LocalBinding/Options/NtClientOptions.cs => src/Core/NosSmooth.LocalBinding/Options/NtClientOptions.cs +27 -0
@@ 0,0 1,27 @@
+//
+// NtClientOptions.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.Structs;
+
+namespace NosSmooth.LocalBinding.Options;
+
+/// <summary>
+/// Options for <see cref="NtClient"/>.
+/// </summary>
+public class NtClientOptions
+{
+ /// <summary>
+ /// Gets or sets the pattern to find static pet manager list address at.
+ /// </summary>
+ public string NtClientPattern { get; set; }
+ = "FF ?? ?? ?? ?? 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF 00 00";
+
+ /// <summary>
+ /// Gets or sets the offsets to find the scene manager at from the static address.
+ /// </summary>
+ public int[] NtClientOffsets { get; set; }
+ = { 1 };
+}<
\ No newline at end of file
A src/Core/NosSmooth.LocalBinding/Structs/NtClient.cs => src/Core/NosSmooth.LocalBinding/Structs/NtClient.cs +72 -0
@@ 0,0 1,72 @@
+//
+// NtClient.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>
+/// A NosTale client base object.
+/// </summary>
+public class NtClient : NostaleObject
+{
+ /// <summary>
+ /// Create <see cref="NtClient"/> instance.
+ /// </summary>
+ /// <param name="nosBrowserManager">The NosTale process browser.</param>
+ /// <param name="options">The options.</param>
+ /// <returns>The player manager or an error.</returns>
+ public static Result<NtClient> Create(NosBrowserManager nosBrowserManager, NtClientOptions options)
+ {
+ var networkObjectAddress = nosBrowserManager.Scanner.FindPattern(options.NtClientPattern);
+ if (!networkObjectAddress.Found)
+ {
+ return new BindingNotFoundError(options.NtClientPattern, "NtClient");
+ }
+
+ if (nosBrowserManager.Process.MainModule is null)
+ {
+ return new NotFoundError("Cannot find the main module of the target process.");
+ }
+
+ var staticAddress = (nuint)(nosBrowserManager.Process.MainModule.BaseAddress + networkObjectAddress.Offset);
+ return new NtClient(nosBrowserManager.Memory, staticAddress, options.NtClientOffsets);
+ }
+
+ private readonly IMemory _memory;
+ private readonly int _staticNtClientAddress;
+ private readonly int[] _ntClientOffsets;
+
+ private NtClient(IMemory memory, nuint staticNtClientAddress, int[] ntClientOffsets)
+ : base(memory, nuint.Zero)
+ {
+ _memory = memory;
+ _staticNtClientAddress = (int)staticNtClientAddress;
+ _ntClientOffsets = ntClientOffsets;
+ }
+
+ /// <summary>
+ /// Gets the address to the player manager.
+ /// </summary>
+ public override nuint Address => _memory.FollowStaticAddressOffsets
+ (_staticNtClientAddress, _ntClientOffsets);
+
+ /// <summary>
+ /// Gets the encryption key used for world encryption.
+ /// </summary>
+ public int EncryptionKey
+ {
+ get
+ {
+ _memory.SafeRead(Address + 0x48, out int encryptionKey);
+ return encryptionKey;
+ }
+ }
+}<
\ No newline at end of file