M Local/NosSmooth.LocalCore/Character.cpp => Local/NosSmooth.LocalCore/Character.cpp +15 -34
@@ 1,47 1,28 @@
#include "Character.h"
+#include <windows.h>
using namespace NosSmoothCore;
-
-const BYTE WALK_OBJECT_PATTERN[] = { 0x33, 0xC9, 0x8B, 0x55, 0xFC, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 };
-const BYTE WALK_FUNCTION_PATTERN[] = { 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xEC, 0x53, 0x56, 0x57, 0x66, 0x89, 0x4D, 0xFA };
-
-LPCSTR WALK_OBJECT_MASK = "xxxxxx????x????";
-LPCSTR WALK_FUNCTION_MASK = "xxxxxxxxxxxxx";
+using namespace System;
+using namespace System::Runtime::InteropServices;
Character::Character(ModuleHook moduleHook)
{
- auto walkFunction = moduleHook.FindPattern(WALK_FUNCTION_PATTERN, WALK_FUNCTION_MASK);
- auto walkObject = *(unsigned int*)(moduleHook.FindPattern(WALK_OBJECT_PATTERN, WALK_OBJECT_MASK) + 0x6);
-
- if (walkFunction == 0)
- {
- throw "Could not find walk function.";
- }
-
- if (walkObject == 0)
- {
- throw "Could not find player object.";
- }
-
- _walkFunction = walkFunction;
- _playerObject = walkObject;
+ CharacterUnmanaged::GetInstance()->Setup(moduleHook);
}
-void CallWalk(int x, int y, unsigned int playerObject, unsigned int walkFunction)
+void Character::Walk(int x, int y)
{
DWORD position = (y << 16) | x;
+ CharacterUnmanaged::GetInstance()->Walk(position);
+}
- __asm
- {
- push 1
- xor ecx, ecx
- mov edx, position
- mov eax, dword ptr ds : [playerObject]
- mov eax, dword ptr ds : [eax]
- call walkFunction
- }
+void Character::SetWalkCallback(WalkCallback^ walkCallback)
+{
+ _walkCallback = walkCallback;
+ IntPtr functionPointer = Marshal::GetFunctionPointerForDelegate(walkCallback);
+ CharacterUnmanaged::GetInstance()->SetWalkCallback(static_cast<NativeWalkCallback>(functionPointer.ToPointer()));
}
-void Character::Walk(int x, int y)
+void NosSmoothCore::Character::ResetHooks()
{
- CallWalk(x, y, _playerObject, _walkFunction);
-}>
\ No newline at end of file
+ CharacterUnmanaged::GetInstance()->ResetHooks();
+}
M Local/NosSmooth.LocalCore/Character.h => Local/NosSmooth.LocalCore/Character.h +13 -2
@@ 1,5 1,6 @@
#pragma once
#include "ModuleHook.h"
+#include "CharacterUnmanaged.h"
namespace NosSmoothCore
{
@@ 18,9 19,19 @@ namespace NosSmoothCore
/// <param name="x">The x coordinate to walk to.</param>
/// <param name="y">The y coordinate to walk to.</param>
void Walk(int x, int y);
+
+ /// <summary>
+ /// Registers the callback for walk function.
+ /// </summary>
+ /// <param name="walkCallback">The callback to call.</param>
+ void SetWalkCallback(WalkCallback^ walkCallback);
+
+ /// <summary>
+ /// Reset the registered hooks.
+ /// </summary>
+ void ResetHooks();
private:
- unsigned int _playerObject;
- unsigned int _walkFunction;
+ WalkCallback^ _walkCallback;
};
}
A Local/NosSmooth.LocalCore/CharacterUnmanaged.cpp => Local/NosSmooth.LocalCore/CharacterUnmanaged.cpp +119 -0
@@ 0,0 1,119 @@
+#include "CharacterUnmanaged.h"
+#include <detours.h>
+
+using namespace NosSmoothCore;
+
+const BYTE WALK_OBJECT_PATTERN[] = { 0x33, 0xC9, 0x8B, 0x55, 0xFC, 0xA1, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 };
+const BYTE WALK_FUNCTION_PATTERN[] = { 0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xEC, 0x53, 0x56, 0x57, 0x66, 0x89, 0x4D, 0xFA };
+
+LPCSTR WALK_OBJECT_MASK = "xxxxxx????x????";
+LPCSTR WALK_FUNCTION_MASK = "xxxxxxxxxxxxx";
+
+void CharacterWalkDetourIn()
+{
+ DWORD position = 0;
+
+ __asm
+ {
+ pushad
+ pushfd
+
+ mov position, edx
+ }
+
+ bool isAccepted = CharacterUnmanaged::GetInstance()->ExecuteWalkCallback(position);
+
+ __asm
+ {
+ popfd
+ popad
+ }
+
+ if (isAccepted) {
+ CharacterUnmanaged::GetInstance()->Walk(position);
+ }
+}
+
+// Detour entrypoint
+// declspec naked to not mess up the stack
+void __declspec(naked) CharacterWalkDetour()
+{
+ unsigned int returnPush;
+ __asm {
+ pop eax
+ pop ebx
+ mov returnPush, eax // we have to push this value on the stack before returning
+ }
+
+ CharacterWalkDetourIn();
+
+ __asm {
+ push returnPush
+ ret
+ }
+}
+
+CharacterUnmanaged::CharacterUnmanaged()
+{
+}
+
+void CharacterUnmanaged::Setup(ModuleHook moduleHook)
+{
+ auto walkFunction = moduleHook.FindPattern(WALK_FUNCTION_PATTERN, WALK_FUNCTION_MASK);
+ auto walkObject = *(unsigned int*)(moduleHook.FindPattern(WALK_OBJECT_PATTERN, WALK_OBJECT_MASK) + 0x6);
+
+ if (walkFunction == 0)
+ {
+ throw "Could not find walk function.";
+ }
+
+ if (walkObject == 0)
+ {
+ throw "Could not find player object.";
+ }
+
+ _walkFunctionAddress = walkFunction;
+ _characterObjectAddress = walkObject;
+}
+
+void CharacterUnmanaged::SetWalkCallback(NativeWalkCallback walkCallback)
+{
+ _walkCallback = walkCallback;
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+ DetourAttach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour);
+ DetourTransactionCommit();
+}
+
+void CharacterUnmanaged::Walk(DWORD position)
+{
+ unsigned int walkFunction = _walkFunctionAddress;
+ unsigned int characterObject = _characterObjectAddress;
+
+ __asm
+ {
+ push 1
+ xor ecx, ecx
+ mov edx, position
+ mov eax, dword ptr ds : [characterObject]
+ mov eax, dword ptr ds : [eax]
+ call walkFunction
+ }
+}
+
+void CharacterUnmanaged::ResetHooks()
+{
+ DetourTransactionBegin();
+ DetourUpdateThread(GetCurrentThread());
+ DetourDetach(&(PVOID&)_walkFunctionAddress, CharacterWalkDetour);
+ DetourTransactionCommit();
+}
+
+bool CharacterUnmanaged::ExecuteWalkCallback(const DWORD position)
+{
+ if (_walkCallback != nullptr) {
+ return _walkCallback(position);
+ }
+
+ return true;
+}<
\ No newline at end of file
A Local/NosSmooth.LocalCore/CharacterUnmanaged.h => Local/NosSmooth.LocalCore/CharacterUnmanaged.h +56 -0
@@ 0,0 1,56 @@
+#pragma once
+#include "ModuleHook.h"
+
+namespace NosSmoothCore
+{
+ public delegate bool WalkCallback(int position);
+ typedef bool(__stdcall* NativeWalkCallback)(int position);
+
+ class CharacterUnmanaged
+ {
+ public:
+ /// <summary>
+ /// Set ups the addresses of objects.
+ /// </summary>
+ /// <param name="moduleHook">The hooking module holding the information about NostaleX.dat</param>
+ void Setup(NosSmoothCore::ModuleHook moduleHook);
+
+ /// <summary>
+ /// Starts walking to the specified x, y position
+ /// </summary>
+ /// <param name="x">The coordinate to walk to.</param>
+ void Walk(DWORD position);
+
+ /// <summary>
+ /// Registers the callback for walk function.
+ /// </summary>
+ /// <param name="walkCallback">The callback to call.</param>
+ void SetWalkCallback(NativeWalkCallback walkCallback);
+
+ /// <summary>
+ /// Reset the registered hooks.
+ /// </summary>
+ void ResetHooks();
+
+ /// <summary>
+ /// Executes the walk callback.
+ /// </summary>
+ /// <param name="position">The coordinate the user wants to walk to.</param>
+ /// <returns>Whether to accept the walk.</returns>
+ bool ExecuteWalkCallback(const DWORD position);
+
+ static CharacterUnmanaged* GetInstance()
+ {
+ static CharacterUnmanaged instance;
+ return reinterpret_cast<CharacterUnmanaged*>(&instance);
+ }
+ unsigned int _walkFunctionAddress;
+ unsigned int _characterObjectAddress;
+ private:
+ CharacterUnmanaged();
+
+
+ NativeWalkCallback _walkCallback;
+ };
+}
+
M Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp => Local/NosSmooth.LocalCore/NetworkUnmanaged.cpp +11 -3
@@ 1,6 1,8 @@
#include "NetworkUnmanaged.h"
#include <detours.h>
#include <windows.h>
+#include <chrono>
+#include <iostream>
using namespace NosSmoothCore;
@@ 35,7 37,7 @@ void PacketSendDetour()
popfd
popad
}
-
+
if (isAccepted) {
NetworkUnmanaged::GetInstance()->SendPacket(packet);
}
@@ 93,8 95,8 @@ void NetworkUnmanaged::Setup(ModuleHook moduleHook)
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
- DetourAttach(&reinterpret_cast<void*&>(_sendPacketAddress), PacketSendDetour);
DetourAttach(&(PVOID&)_receivePacketAddress, PacketReceiveDetour);
+ DetourAttach(&reinterpret_cast<void*&>(_sendPacketAddress), PacketSendDetour);
DetourTransactionCommit();
}
@@ 129,8 131,14 @@ void NetworkUnmanaged::ResetHooks()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
- DetourDetach(&reinterpret_cast<void*&>(_sendPacketAddress), PacketSendDetour);
+ if (_sendCallback != nullptr) {
+ DetourDetach(&reinterpret_cast<void*&>(_sendPacketAddress), PacketSendDetour);
+ }
+
+ if (_receiveCallback != nullptr) {
DetourDetach(&(PVOID&)_receivePacketAddress, PacketReceiveDetour);
+ }
+
DetourTransactionCommit();
}
M Local/NosSmooth.LocalCore/NosSmooth.LocalCore.vcxproj => Local/NosSmooth.LocalCore/NosSmooth.LocalCore.vcxproj +3 -0
@@ 166,6 166,7 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="Character.h" />
+ <ClInclude Include="CharacterUnmanaged.h" />
<ClInclude Include="ModuleHook.h" />
<ClInclude Include="Network.h" />
<ClInclude Include="NetworkUnmanaged.h" />
@@ 174,12 175,14 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="Character.cpp" />
+ <ClCompile Include="CharacterUnmanaged.cpp" />
<ClCompile Include="ModuleHook.cpp" />
<ClCompile Include="Network.cpp" />
<ClCompile Include="NetworkUnmanaged.cpp" />
<ClCompile Include="NosSmoothCore.cpp" />
</ItemGroup>
<ItemGroup>
+ <None Include="..\..\stylecop.json" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
M Local/NosSmooth.LocalCore/NosSmooth.LocalCore.vcxproj.filters => Local/NosSmooth.LocalCore/NosSmooth.LocalCore.vcxproj.filters +7 -0
@@ 33,6 33,9 @@
<ClInclude Include="NetworkUnmanaged.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="CharacterUnmanaged.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="NosSmoothCore.cpp">
@@ 50,8 53,12 @@
<ClCompile Include="NetworkUnmanaged.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="CharacterUnmanaged.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
+ <None Include="..\..\stylecop.json" />
</ItemGroup>
</Project>=
\ No newline at end of file
M Local/NosSmooth.LocalCore/NosSmoothCore.cpp => Local/NosSmooth.LocalCore/NosSmoothCore.cpp +1 -0
@@ 30,4 30,5 @@ Network^ NosClient::GetNetwork()
void NosClient::ResetHooks()
{
_network->ResetHooks();
+ _character->ResetHooks();
}=
\ No newline at end of file