Skip to content

Commit

Permalink
Switched to better UpdateLoop hook. Added async get/set for memory ma…
Browse files Browse the repository at this point in the history
…nager methods that take path
  • Loading branch information
gurrenm3 committed Jun 28, 2022
1 parent 7c42f56 commit 4b34b41
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 44 deletions.
83 changes: 83 additions & 0 deletions NoMansSky.Api/Extensions/MemoryManagerExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using Reloaded.ModHelper;
using System;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace NoMansSky.Api
{
Expand All @@ -10,6 +12,32 @@ public static class MemoryManagerExtensions
{
private static MemoryManagerCache cache = new MemoryManagerCache();

/// <summary>
/// Sets an object in memory at the provided address on a separate thread and returns when its done.
/// Use this for big objects so you don't lock the game.
/// <br/><br/>Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <param name="valueToSet"></param>
/// <returns></returns>
public static async Task SetValueAsync(this MemoryManager manager, string pathToValue, object valueToSet)
{
try
{
await Task.Run(() => manager.SetValue(pathToValue, valueToSet));
}
catch (Exception ex) { throw ex; }
}

/// <summary>
/// Sets an object in memory at the provided address. Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <param name="valueToSet"></param>
public static void SetValue(this MemoryManager manager, string pathToValue, object valueToSet)
{
if (string.IsNullOrEmpty(pathToValue))
Expand All @@ -30,6 +58,53 @@ public static void SetValue(this MemoryManager manager, string pathToValue, obje
manager.SetValue(addressInfo.address, valueToSet);
}


/// <summary>
/// Reads an object in memory on a separate thread and returns when its done.
/// Use this for big objects so you don't lock the game.
/// <br/><br/>Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <returns></returns>
public static async Task<object> GetValueAsync(this MemoryManager manager, string pathToValue)
{
try
{
return await Task.Run(() => manager.GetValue(pathToValue));
}
catch (Exception ex) { throw ex; }
}

/// <summary>
/// Reads an object in memory on a separate thread and returns when its done.
/// Use this for big objects so you don't lock the game.
/// <br/><br/>Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <returns></returns>
public static async Task<T> GetValueAsync<T>(this MemoryManager manager, string pathToValue)
{
try
{
var value = await Task.Run(() => manager.GetValue<T>(pathToValue));
return value == null ? default(T) : (T)value;
}
catch (Exception ex) { throw ex; }
}


/// <summary>
/// Reads an object in memory. Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <returns></returns>
public static object GetValue(this MemoryManager manager, string pathToValue)
{
if (string.IsNullOrEmpty(pathToValue))
Expand All @@ -43,6 +118,14 @@ public static object GetValue(this MemoryManager manager, string pathToValue)
return value;
}

/// <summary>
/// Reads an object in memory. Takes a full path to the object you want to set.
/// <br/>Example: pathToValue = "GcPlayerGlobals.GroundRunSpeed"
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="manager"></param>
/// <param name="pathToValue"></param>
/// <returns></returns>
public static T GetValue<T>(this MemoryManager manager, string pathToValue)
{
var value = manager.GetValue(pathToValue);
Expand Down
1 change: 1 addition & 0 deletions NoMansSky.Api/Game Classes/Game Stuff/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ private void Initialize()
_instance = this;
IGame.Instance = this;

//GameLoop = new HookedGameLoop();
GameLoop = new HookedGameLoop();
GameLoop.Initialize();

Expand Down
21 changes: 15 additions & 6 deletions NoMansSky.Api/Hooks/GameHooks/Game_Update.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Reloaded.Hooks.Definitions.X64;
using Reloaded.ModHelper;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace NoMansSky.Api.Hooks.GameHooks
Expand All @@ -12,7 +13,7 @@ public unsafe class Game_Update : IModHook

[Function(CallingConventions.Microsoft)]
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public delegate double HookDelegate();
public delegate void HookDelegate(long a1, double a2);
public static IFunction<HookDelegate> Function { get; set; }
public static IHook<HookDelegate> Hook;

Expand All @@ -26,27 +27,35 @@ public unsafe class Game_Update : IModHook
public string HookName => "Game_Update";
private HookedTime time => Game.Instance.GameLoop.Time as HookedTime;
private IModLogger logger;
private Stopwatch stopwatch;


public void InitHook(IModLogger _logger, IReloadedHooks _hooks)
{
logger = _logger;

string pattern = "40 53 48 83 EC 20 48 8D 4C 24 ? FF 15 ? ? ? ? 48 8B 5C 24 ? 48 8D 4C 24 ? FF 15 ? ? ? ? F2";
//string pattern = "40 53 48 83 EC 20 48 8D 4C 24 ? FF 15 ? ? ? ? 48 8B 5C 24 ? 48 8D 4C 24 ? FF 15 ? ? ? ? F2";
string pattern = "41 56 48 83 EC 60 48 8B 41 58";
Function = _hooks.CreateFunction<HookDelegate>(new Signature(pattern).Scan());
Hook = Function.Hook(CodeToExecute).Activate();
}

private double CodeToExecute()
private void CodeToExecute(long a1, double a2)
{
if (stopwatch == null)
{
stopwatch = new Stopwatch();
stopwatch.Start();
}

ModEventHook.Prefix.Invoke();

double elapsedTime = Hook.OriginalFunction();
Hook.OriginalFunction(a1, a2);

var elapsedTime = stopwatch.Elapsed.TotalMilliseconds;
time.Update(elapsedTime);

ModEventHook.Postfix.Invoke();

return elapsedTime;
}
}
}
45 changes: 7 additions & 38 deletions NoMansSky.Api/Mod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,17 @@ public Mod(IModConfig _config, IReloadedHooks _hooks, IModLogger _logger) : base
Game.OnMainMenu += OnMainMenu;
/*Game.OnMainMenu += () => GlobalMbinModding();
*/

Game.GameLoop.OnUpdate.Postfix += () =>
{
var deltaTime = GameLoop.Time.DeltaTime;
Logger.WriteLine(deltaTime);
};
}

private void OnMainMenu()
{
playerGlobalsAddress = Game.MBinManager.GetMbin("GcPlayerGlobals").Address;

/*float x = memoryMgr.GetValue<float>("GcPlayerGlobals.BinocularScopeOffset.x");
float y = memoryMgr.GetValue<float>("GcPlayerGlobals.BinocularScopeOffset.y");
float z = memoryMgr.GetValue<float>("GcPlayerGlobals.BinocularScopeOffset.z");
Logger.WriteLine($"({x}, {y}, {z})");*/

/*Vector3f scopeOffset = memoryMgr.GetValue<Vector3f>("GcPlayerGlobals.BinocularScopeOffset");
Logger.WriteLine($"({scopeOffset.x}, {scopeOffset.y}, {scopeOffset.z})");
Logger.WriteLine("Address: " + Game.MBinManager.GetMbin("GcPlayerGlobals").Address.ToHex());
var offset = NMSTemplate.OffsetOf("GcPlayerGlobals", "BinocularScopeOffset");
Logger.WriteLine($"Offset {offset}");*/

//memoryMgr.SetValue("GcPlayerGlobals.GroundRunSpeed", currentValue + 1);
}


Expand All @@ -65,30 +57,7 @@ private void PrintInventory()
long playerGlobalsAddress = 0;
public async override void Update()
{
if (Keyboard.IsPressed(Key.RightArrow))
{
MemoryManager memoryMgr = new MemoryManager();

var global = await memoryMgr.GetValueAsync<GcPlayerGlobals>(playerGlobalsAddress);
global.GroundRunSpeed += 1;
await memoryMgr.SetValueAsync(playerGlobalsAddress, global);
Logger.WriteLine("Done setting global");
//memoryMgr.SetValue("GcPlayerGlobals.BinocularRangeSpace", 69);
}
/*if (Keyboard.IsPressed(Key.UpArrow))
{
Logger.WriteLine("Up arrow pressed. Raising sprint speed by 1");
globalMbin.GroundRunSpeed += 1;
memoryMgr.SetValue(variableAddress, globalMbin.GroundRunSpeed);
}
if (Keyboard.IsPressed(Key.DownArrow))
{
Logger.WriteLine("Down arrow pressed. Reducing sprint speed by 1");
globalMbin.GroundRunSpeed -= 1;
memoryMgr.SetValue(variableAddress, globalMbin.GroundRunSpeed);
}*/

}

internal static void WriteLine(string message) => Instance?.Logger?.WriteLine(message);
Expand Down

0 comments on commit 4b34b41

Please sign in to comment.