HunterPie.Native: added input interrupt & server logging messages
MODIFY
HunterPie.Core/Core/Native/VirtualInput.cs
HunterPie.Core/Core/Native/VirtualInput.cs
@@ -12,6 +12,10 @@ namespace HunterPie.Core.Input
{
private static VirtualInput instance;
private bool disposedValue;
+ private Random random = new Random();
+
+ private uint lastInputId = 0;
+ public static uint LastInputId => Instance.lastInputId;
public static VirtualInput Instance
{
@@ -97,10 +101,11 @@ namespace HunterPie.Core.Input
{
do
{
- newInjId = (uint)(new Random().NextDouble() * uint.MaxValue);
+ newInjId = (uint)(random.NextDouble() * uint.MaxValue);
} while (pendingRequests.ContainsKey(newInjId));
pendingRequests.Add(newInjId, src);
+ this.lastInputId = newInjId;
}
C_QUEUE_INPUT packet = new C_QUEUE_INPUT()
@@ -120,6 +125,42 @@ namespace HunterPie.Core.Input
return await src.Task;
}
+ public static async Task InterruptInput(uint id)
+ {
+ var packet = new C_INTERRUPT_INPUT()
+ {
+ header = new Header() { opcode = OPCODE.InterruptInput, version = 1 },
+ type = INPUT_INTERRUPT_TYPE.by_id,
+ inputId = id
+ };
+
+ await Client.ToServer(packet);
+ }
+
+ public static async Task InterruptAllInput()
+ {
+ var packet = new C_INTERRUPT_INPUT()
+ {
+ header = new Header() { opcode = OPCODE.InterruptInput, version = 1 },
+ type = INPUT_INTERRUPT_TYPE.clear,
+ inputId = 0
+ };
+
+ await Client.ToServer(packet);
+ }
+
+ public static async Task InterruptLastInput()
+ {
+ var packet = new C_INTERRUPT_INPUT()
+ {
+ header = new Header() { opcode = OPCODE.InterruptInput, version = 1 },
+ type = INPUT_INTERRUPT_TYPE.last,
+ inputId = 0
+ };
+
+ await Client.ToServer(packet);
+ }
+
private static byte[] CalculateInputs(char[] keys)
{
byte[] bits = new byte[32];

MODIFY
HunterPie.Core/HunterPie.Core.csproj
HunterPie.Core/HunterPie.Core.csproj
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
- <LangVersion>7.3</LangVersion>
+ <LangVersion>9</LangVersion>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

MODIFY
HunterPie.Core/Native/Connection/Client.cs
HunterPie.Core/Native/Connection/Client.cs
@@ -203,6 +203,13 @@ namespace HunterPie.Native.Connection
OnDamageDealResponse?.Invoke(this, pkt);
break;
}
+
+ case OPCODE.LogMessage:
+ {
+ S_LOG_MESSAGE pkt = PacketParser.Deserialize<S_LOG_MESSAGE>(buffer);
+ Debugger.Write("[Native] " + pkt.message, "#FFC88DF2");
+ break;
+ }
}
}

MODIFY
HunterPie.Core/Native/Connection/Packets/Definitions.cs
HunterPie.Core/Native/Connection/Packets/Definitions.cs
@@ -100,6 +100,27 @@ namespace HunterPie.Native.Connection.Packets
public bool isTenderized;
public int attackId;
}
+ public enum INPUT_INTERRUPT_TYPE
+ {
+ last,
+ by_id,
+ clear
+ };
+ [StructLayout(LayoutKind.Sequential)]
+ public struct C_INTERRUPT_INPUT
+ {
+ public Header header;
+ public INPUT_INTERRUPT_TYPE type;
+ public uint inputId;
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct S_LOG_MESSAGE
+ {
+ public Header header;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string message;
+ }
#region Other Data structures

MODIFY
HunterPie.Core/Native/Connection/Packets/Opcodes.cs
HunterPie.Core/Native/Connection/Packets/Opcodes.cs
QueueInput,
SendChatMessage,
SendSystemMessage,
- DealDamage
+ DealDamage,
+ InterruptInput,
+ LogMessage
}
}

MODIFY
HunterPie.Native/Connection/Packets/Definitions.h
HunterPie.Native/Connection/Packets/Definitions.h
@@ -46,6 +46,18 @@ namespace Connection
unsigned int inputId;
};
+ enum INPUT_INTERRUPT_TYPE
+ {
+ last,
+ by_id,
+ clear
+ };
+ typedef struct C_INTERRUPT_INPUT : I_PACKET
+ {
+ INPUT_INTERRUPT_TYPE type;
+ unsigned int inputId;
+ };
+
typedef struct C_SEND_CHAT : I_PACKET
{
char message[256];
@@ -68,5 +80,10 @@ namespace Connection
int attackId;
};
+ typedef struct S_LOG_MESSAGE : I_PACKET
+ {
+ char message[256];
+ };
+
}
}

MODIFY
HunterPie.Native/Connection/Packets/model.h
HunterPie.Native/Connection/Packets/model.h
@@ -14,7 +14,9 @@ namespace Connection
QueueInput,
SendChatMessage,
SendSystemMessage,
- DealDamage
+ DealDamage,
+ InterruptInput,
+ LogMessage
};
typedef struct header

MODIFY
HunterPie.Native/Connection/Socket.cpp
HunterPie.Native/Connection/Socket.cpp
@@ -174,6 +174,17 @@ void Connection::Server::receivePackets(char buffer[DEFAULT_BUFFER_SIZE])
break;
}
+ case OPCODE::InterruptInput:
+ {
+ LOG("-> C_INTERRUPT_INPUT\n");
+ C_INTERRUPT_INPUT pkt = *reinterpret_cast<C_INTERRUPT_INPUT*>(buffer);
+
+ inputQueueMutex.lock();
+ inputInterruptQueue.push(&pkt);
+ inputQueueMutex.unlock();
+ break;
+ }
+
case OPCODE::SendChatMessage:
{
C_SEND_CHAT pkt = *reinterpret_cast<C_SEND_CHAT*>(buffer);

MODIFY
HunterPie.Native/Connection/Socket.h
HunterPie.Native/Connection/Socket.h
@@ -16,6 +16,7 @@ namespace Connection
{
public:
std::queue<Packets::input*> inputInjectionToQueue;
+ std::queue<Packets::C_INTERRUPT_INPUT*> inputInterruptQueue;
std::mutex inputQueueMutex;
static Server* getInstance();

MODIFY
HunterPie.Native/Game/Damage/damage.cpp
HunterPie.Native/Game/Damage/damage.cpp
@@ -56,12 +56,33 @@ void Game::Damage::HunterPie_DealDamage(
void Game::Damage::InitializeHooks()
{
- MH_CreateHook(
+ MH_STATUS s = MH_CreateHook(
(fnDealDamage)FunDealDamage,
&HunterPie_DealDamage,
reinterpret_cast<LPVOID*>(&originalDealDamage)
);
+ S_LOG_MESSAGE packet{};
+ packet.header.opcode = OPCODE::LogMessage;
+ packet.header.version = 1;
+
+ if (s != MH_OK) {
+ LOG("Game::Damage::InitializeHooks %s\n", MH_StatusToString(s));
+
+ sprintf_s(packet.message
+ , sizeof(packet.message)
+ , "Error on Damage hook %s", MH_StatusToString(s)
+ );
+ }
+ else
+ {
+ sprintf_s(packet.message
+ , sizeof(packet.message)
+ , "Damage Hook initialized successfully"
+ );
+ }
+ Connection::Server::getInstance()->sendData(&packet, sizeof(packet));
+
}
bool Game::Damage::LoadAddress(uintptr_t ptrs[128])

MODIFY
HunterPie.Native/Game/Input/input.cpp
HunterPie.Native/Game/Input/input.cpp
@@ -25,8 +25,26 @@ void Game::Input::InitializeHooks()
&HunterPie_HandleKeyboardInput,
reinterpret_cast<LPVOID*>(&originalHandleInput));
- if (s != MH_OK)
- LOG("%s\n", MH_StatusToString(s));
+ S_LOG_MESSAGE packet{};
+ packet.header.opcode = OPCODE::LogMessage;
+ packet.header.version = 1;
+
+ if (s != MH_OK) {
+ LOG("Game::Input::InitializeHooks %s\n", MH_StatusToString(s));
+
+ sprintf_s(packet.message
+ , sizeof(packet.message)
+ , "Error on Input hook %s", MH_StatusToString(s)
+ );
+ }
+ else
+ {
+ sprintf_s(packet.message
+ , sizeof(packet.message)
+ , "Input Hook initialized successfully"
+ );
+ }
+ Connection::Server::getInstance()->sendData(&packet, sizeof(packet));
}
void InjectInput(sMhKeyboard* keyboard)
@@ -35,11 +53,14 @@ void InjectInput(sMhKeyboard* keyboard)
{
input* currentInput = inputInjectionQueue.front();
+ if (currentInput->nFrames != 0)
+ {
if (currentInput->ignoreOriginalInputs)
{
memcpy(keyboard->firstArray, currentInput->inputArray, sizeof(keyboard->firstArray));
memcpy(keyboard->thirdArray, currentInput->inputArray, sizeof(keyboard->thirdArray));
- } else
+ }
+ else
{
for (int i = 0; i < sizeof(keyboard->firstArray); i++)
{
@@ -47,6 +68,7 @@ void InjectInput(sMhKeyboard* keyboard)
keyboard->thirdArray[i] |= currentInput->inputArray[i];
}
}
+ }
keyboardInputElapsedFrames++;
if (currentInput->nFrames <= keyboardInputElapsedFrames)
@@ -58,7 +80,7 @@ void InjectInput(sMhKeyboard* keyboard)
delete inputInjectionQueue.front();
- inputInjectionQueue.pop();
+ inputInjectionQueue.pop_front();
Connection::Server::getInstance()->sendData(&packet, sizeof(packet));
@@ -77,14 +99,60 @@ void Game::Input::HunterPie_HandleKeyboardInput(sMhKeyboard* keyboard)
{
std::queue<input*>& sharedQueue = Server::getInstance()->inputInjectionToQueue;
+ std::queue<C_INTERRUPT_INPUT*>& interruptQueue = Server::getInstance()->inputInterruptQueue;
if (!sharedQueue.empty())
{
input* toQueue = sharedQueue.front();
- inputInjectionQueue.push(toQueue);
+ inputInjectionQueue.push_front(toQueue);
sharedQueue.pop();
}
+ while (!interruptQueue.empty())
+ {
+ switch (const auto pkt = interruptQueue.front(); pkt->type)
+ {
+ case last: {
+ if (!inputInjectionQueue.empty()) {
+ input* front = inputInjectionQueue.front();
+ front->nFrames = 0;
+ LOG(" itrp last - ok\n");
+ }
+ else
+ {
+ LOG(" itrp last - empty\n");
+ }
+ break;
+ }
+
+ case by_id: {
+ bool ok = false;
+
+ for (auto input : inputInjectionQueue)
+ {
+ if (input->injectionId == pkt->inputId)
+ {
+ ok = true;
+ input->nFrames = 0;
+ break;
+ }
+ }
+ LOG(" itrp by id %s\n", ok ? "OK" : "not found");
+ break;
+ }
+
+ case clear:
+ for (auto input : inputInjectionQueue)
+ {
+ input->nFrames = 0;
+ }
+ LOG(" itrp all %llu\n", inputInjectionQueue.size());
+ break;
+ }
+
+ interruptQueue.pop();
+ }
+
inputQueueMtx.unlock();
}

MODIFY
HunterPie.Native/Game/Input/input.h
HunterPie.Native/Game/Input/input.h
@@ -29,6 +29,6 @@ namespace Game
void InitializeHooks();
bool LoadAddress(uintptr_t ptrs[128]);
- static std::queue<Connection::Packets::input*> inputInjectionQueue;
+ static std::deque<Connection::Packets::input*> inputInjectionQueue;
}
}

HunterPie.Native: added input interrupt & server logging messages