minor changes
- cheat-base: add support dx12 add several utility modifications - cheat-library: refactored sniffer. Check: https://github.com/Akebi-Group/Akebi-PacketSniffer
This commit is contained in:
parent
d975e5ee58
commit
4d44b45b7e
@ -125,7 +125,7 @@
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)framework\;$(ProjectDir)src\;$(ProjectDir)vendor\detours\;$(ProjectDir)vendor\fmt\include\;$(ProjectDir)vendor\imgui\;$(ProjectDir)vendor\magic_enum\include\;$(ProjectDir)vendor\simpleIni\;$(ProjectDir)vendor\json\single_include\;$(ProjectDir)vendor\imgui-notify-v2\;$(ProjectDir)vendor\stb\</AdditionalIncludeDirectories>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -158,7 +158,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -193,7 +193,7 @@
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<OmitFramePointers>false</OmitFramePointers>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>
|
||||
@ -222,7 +222,7 @@
|
||||
<PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<SupportJustMyCode>false</SupportJustMyCode>
|
||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||
@ -242,7 +242,7 @@
|
||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
||||
@ -259,7 +259,7 @@
|
||||
<PreprocessorDefinitions>_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS;_CRT_SECURE_NO_WARNINGS;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
<LanguageStandard_C>stdc17</LanguageStandard_C>
|
||||
<LanguageStandard_C>Default</LanguageStandard_C>
|
||||
</ClCompile>
|
||||
<Lib>
|
||||
<AdditionalDependencies>detours-$(PlatformShortName).lib</AdditionalDependencies>
|
||||
@ -298,6 +298,8 @@
|
||||
<ClInclude Include="src\cheat-base\events\joins\handlereventjoin.hpp" />
|
||||
<ClInclude Include="src\cheat-base\inject\load-library.h" />
|
||||
<ClInclude Include="src\cheat-base\inject\manual-map.h" />
|
||||
<ClInclude Include="src\cheat-base\ISerializable.h" />
|
||||
<ClInclude Include="src\cheat-base\render\backend\dx12-hook.h" />
|
||||
<ClInclude Include="src\cheat-base\ResourceLoader.h" />
|
||||
<ClInclude Include="src\cheat-base\Hotkey.h" />
|
||||
<ClInclude Include="src\cheat-base\render\ImageLoader.h" />
|
||||
@ -335,6 +337,7 @@
|
||||
<ClInclude Include="vendor\imgui-notify-v2\font_awesome_5.h" />
|
||||
<ClInclude Include="vendor\imgui-notify-v2\imgui_notify.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx11.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx12.h" />
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_win32.h" />
|
||||
<ClInclude Include="vendor\imgui\imconfig.h" />
|
||||
<ClInclude Include="vendor\imgui\imgui.h" />
|
||||
@ -365,6 +368,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp" />
|
||||
<ClCompile Include="src\cheat-base\inject\manual-map.cpp" />
|
||||
<ClCompile Include="src\cheat-base\render\backend\dx12-hook.cpp" />
|
||||
<ClCompile Include="src\cheat-base\ResourceLoader.cpp" />
|
||||
<ClCompile Include="src\cheat-base\Hotkey.cpp" />
|
||||
<ClCompile Include="src\cheat-base\render\ImageLoader.cpp" />
|
||||
@ -410,6 +414,14 @@
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release_WS|Win32'">pch.h</PrecompiledHeaderFile>
|
||||
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_dx12.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|Win32'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_win32.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">NotUsing</PrecompiledHeader>
|
||||
|
@ -243,6 +243,15 @@
|
||||
<ClInclude Include="src\cheat-base\inject\load-library.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\cheat-base\ISerializable.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\cheat-base\render\backend\dx12-hook.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vendor\imgui\backends\imgui_impl_dx12.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\cheat-base\util.cpp">
|
||||
@ -335,5 +344,11 @@
|
||||
<ClCompile Include="src\cheat-base\inject\load-library.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\cheat-base\render\backend\dx12-hook.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vendor\imgui\backends\imgui_impl_dx12.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -17,7 +17,7 @@ public:
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
[[nodiscard]] static Fn getOrigin(Fn handler, const char* callerName = nullptr) noexcept
|
||||
static Fn getOrigin(Fn handler, const char* callerName = nullptr) noexcept
|
||||
{
|
||||
if (holderMap.count(reinterpret_cast<void*>(handler)) == 0) {
|
||||
LOG_WARNING("Origin not found for handler: %s. Maybe racing bug.", callerName == nullptr ? "<Unknown>" : callerName);
|
||||
@ -27,14 +27,17 @@ public:
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
[[nodiscard]] static void detach(Fn handler) noexcept
|
||||
static void detach(Fn handler) noexcept
|
||||
{
|
||||
disable(handler);
|
||||
holderMap.erase(reinterpret_cast<void*>(handler));
|
||||
}
|
||||
|
||||
// I don't know why
|
||||
#ifdef _WIN64
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
[[nodiscard]] static RType call(RType(*handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
static RType call(RType(*handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
@ -43,6 +46,30 @@ public:
|
||||
return RType();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
static RType call(RType(__cdecl *handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
return origin(params...);
|
||||
|
||||
return RType();
|
||||
}
|
||||
|
||||
template <typename RType, typename... Params>
|
||||
static RType call(RType(__stdcall *handler)(Params...), const char* callerName = nullptr, Params... params)
|
||||
{
|
||||
auto origin = getOrigin(handler, callerName);
|
||||
if (origin != nullptr)
|
||||
return origin(params...);
|
||||
|
||||
return RType();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void detachAll() noexcept
|
||||
{
|
||||
for (const auto &[key, value] : holderMap)
|
||||
|
20
cheat-base/src/cheat-base/ISerializable.h
Normal file
20
cheat-base/src/cheat-base/ISerializable.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class ISerializable
|
||||
{
|
||||
public:
|
||||
virtual void to_json(nlohmann::json& j) const = 0;
|
||||
virtual void from_json(const nlohmann::json& j) = 0;
|
||||
};
|
||||
|
||||
inline void to_json(nlohmann::json& j, const ISerializable& ser)
|
||||
{
|
||||
ser.to_json(j);
|
||||
}
|
||||
|
||||
inline void from_json(const nlohmann::json& j, ISerializable& ser)
|
||||
{
|
||||
ser.from_json(j);
|
||||
}
|
@ -16,18 +16,22 @@ PipeTransfer::PipeTransfer(const std::string& name)
|
||||
|
||||
PipeTransfer::~PipeTransfer()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
Close();
|
||||
}
|
||||
|
||||
bool PipeTransfer::Create()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
Close();
|
||||
m_Pipe = CreateNamedPipe(m_Name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 256 * 1024, 16, INFINITE, NULL);
|
||||
return IsPipeOpened();
|
||||
}
|
||||
|
||||
void PipeTransfer::Close()
|
||||
{
|
||||
if (m_Pipe)
|
||||
CloseHandle(m_Pipe);
|
||||
}
|
||||
|
||||
bool PipeTransfer::IsPipeOpened()
|
||||
{
|
||||
return m_Pipe && m_Pipe != INVALID_HANDLE_VALUE;
|
||||
|
@ -20,6 +20,7 @@ public:
|
||||
~PipeTransfer();
|
||||
|
||||
bool Create();
|
||||
void Close();
|
||||
bool Connect();
|
||||
bool WaitForConnection();
|
||||
bool IsPipeOpened();
|
||||
|
@ -10,9 +10,9 @@
|
||||
namespace cheat
|
||||
{
|
||||
|
||||
void CheatManagerBase::Init(LPBYTE pFontData, DWORD dFontDataSize)
|
||||
void CheatManagerBase::Init(LPBYTE pFontData, DWORD dFontDataSize, renderer::DXVersion dxVersion)
|
||||
{
|
||||
renderer::Init(pFontData, dFontDataSize);
|
||||
renderer::Init(pFontData, dFontDataSize, dxVersion);
|
||||
|
||||
events::RenderEvent += MY_METHOD_HANDLER(CheatManagerBase::OnRender);
|
||||
events::KeyUpEvent += MY_METHOD_HANDLER(CheatManagerBase::OnKeyUp);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <cheat-base/cheat/Feature.h>
|
||||
#include <cheat-base/config/Config.h>
|
||||
#include <cheat-base/events/event.hpp>
|
||||
#include <cheat-base/render/renderer.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
@ -30,7 +31,7 @@ namespace cheat
|
||||
void OnWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool& cancelled);
|
||||
void OnRender();
|
||||
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize);
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize, renderer::DXVersion dxVersion = renderer::DXVersion::D3D11);
|
||||
|
||||
virtual void CursorSetVisibility(bool visibility) = 0;
|
||||
virtual bool CursorGetVisibility() = 0;
|
||||
|
@ -6,7 +6,11 @@
|
||||
#include "fields/Toggle.h"
|
||||
#include "fields/Enum.h"
|
||||
|
||||
#define NFEX(field, friendName, name, section, defaultValue, shared) field##(config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, defaultValue))
|
||||
#define SNFEX(field, friendName, name, section, defaultValue, shared) config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, defaultValue)
|
||||
#define SNFB(field, name, section, defaultValue, shared) SNFEX(field, name, config::internal::FixFieldName(#field), section, defaultValue, shared)
|
||||
#define SNF(field, name, section, defaultValue) SNFB(field, name, section, defaultValue, false)
|
||||
|
||||
#define NFEX(field, friendName, name, section, defaultValue, shared) field##(SNFEX(field, friendName, name, section, defaultValue, shared))
|
||||
#define NFEXUP(field, friendName, name, section, shared, ...) field##(config::CreateField<decltype(##field##)::_ValueType>(friendName, name, section, shared, __VA_ARGS__))
|
||||
|
||||
#define NFB(field, name, section, defaultValue, shared) NFEX(field, name, config::internal::FixFieldName(#field), section, defaultValue, shared)
|
||||
|
@ -112,6 +112,13 @@ namespace config::internal
|
||||
return *this;
|
||||
}
|
||||
|
||||
FieldBase<T>& operator=(T&& other)
|
||||
{
|
||||
p_Container->m_Value = std::move(other);
|
||||
p_Container->FireChanged();
|
||||
return *this;
|
||||
}
|
||||
|
||||
FieldBase<T>& operator=(std::shared_ptr<FieldSerialize<T>>& other)
|
||||
{
|
||||
p_Container->ChangedEvent -= MY_METHOD_HANDLER(FieldBase<T>::OnFieldChanged);
|
||||
|
@ -5,6 +5,18 @@
|
||||
|
||||
namespace config::internal
|
||||
{
|
||||
namespace CHECK
|
||||
{
|
||||
struct No {};
|
||||
template<typename T, typename Arg> No operator== (const T&, const Arg&);
|
||||
|
||||
template<typename T, typename Arg = T>
|
||||
struct EqualExists
|
||||
{
|
||||
enum { value = !std::is_same<decltype(std::declval<T>() == std::declval<Arg>()), No>::value };
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class FieldSerialize : public FieldEntry
|
||||
{
|
||||
@ -13,9 +25,13 @@ namespace config::internal
|
||||
FieldEntry(friendlyName, name, sectionName, multiProfile), m_Value(defaultValue), m_DefaultValue(defaultValue) { }
|
||||
|
||||
nlohmann::json ToJson() override
|
||||
{
|
||||
if constexpr (CHECK::EqualExists<T>::value)
|
||||
{
|
||||
if (m_Value == m_DefaultValue)
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
return converters::ToJson(m_Value);
|
||||
}
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <cheat-base/HookManager.h>
|
||||
|
||||
#pragma comment(lib, "D3dcompiler.lib")
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
@ -18,15 +17,20 @@ extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam
|
||||
static IDXGISwapChainPresent fnIDXGISwapChainPresent;
|
||||
static ID3D11Device* pDevice = nullptr;
|
||||
|
||||
static HRESULT __stdcall Present(IDXGISwapChain* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
static HRESULT __stdcall Present_Hook(IDXGISwapChain* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
{
|
||||
static BOOL g_bInitialised = false;
|
||||
|
||||
// Main D3D11 Objects
|
||||
static ID3D11DeviceContext* pContext = nullptr;
|
||||
|
||||
if (!g_bInitialised) {
|
||||
pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
||||
|
||||
if (!g_bInitialised)
|
||||
{
|
||||
auto result = (HRESULT)pChain->GetDevice(__uuidof(pDevice), reinterpret_cast<void**>(&pDevice));
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
pDevice->GetImmediateContext(&pContext);
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC sd;
|
||||
@ -36,19 +40,32 @@ static HRESULT __stdcall Present(IDXGISwapChain* pChain, const UINT SyncInterval
|
||||
|
||||
g_bInitialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
// render function
|
||||
if (g_bInitialised)
|
||||
backend::DX11Events::RenderEvent(pContext);
|
||||
|
||||
return CALL_ORIGIN(Present, pChain, SyncInterval, Flags);
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
static IDXGISwapChainPresent findDirect11Present()
|
||||
{
|
||||
const HWND hWnd = GetForegroundWindow();
|
||||
WNDCLASSEX wc{ 0 };
|
||||
wc.cbSize = sizeof(wc);
|
||||
wc.lpfnWndProc = DefWindowProc;
|
||||
wc.lpszClassName = TEXT("Class");
|
||||
|
||||
if (!RegisterClassEx(&wc))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HWND hWnd = CreateWindow(wc.lpszClassName, TEXT(""), WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, nullptr);
|
||||
|
||||
IDXGISwapChain* pSwapChain;
|
||||
|
||||
constexpr D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0;
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
||||
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
|
||||
swapChainDesc.BufferCount = 1;
|
||||
@ -64,11 +81,15 @@ static IDXGISwapChainPresent findDirect11Present()
|
||||
// Main D3D11 Objects
|
||||
ID3D11DeviceContext* pContext = nullptr;
|
||||
ID3D11Device* pDevice = nullptr;
|
||||
if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&
|
||||
FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)))
|
||||
|
||||
if (/*FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, NULL, NULL, &featureLevel, 1,
|
||||
D3D11_SDK_VERSION, &swapChainDesc, &pSwapChain, &pDevice, NULL, &pContext)) &&*/
|
||||
FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION,
|
||||
&swapChainDesc, &pSwapChain, &pDevice, &featureLevel, nullptr)))
|
||||
{
|
||||
DestroyWindow(swapChainDesc.OutputWindow);
|
||||
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -78,9 +99,12 @@ static IDXGISwapChainPresent findDirect11Present()
|
||||
auto swapChainPresent = reinterpret_cast<IDXGISwapChainPresent>(pSwapChainVtable[8]);
|
||||
|
||||
pDevice->Release();
|
||||
pContext->Release();
|
||||
//pContext->Release();
|
||||
pSwapChain->Release();
|
||||
|
||||
DestroyWindow(swapChainDesc.OutputWindow);
|
||||
UnregisterClass(wc.lpszClassName, GetModuleHandle(nullptr));
|
||||
|
||||
return swapChainPresent;
|
||||
}
|
||||
|
||||
@ -95,7 +119,7 @@ void backend::InitializeDX11Hooks()
|
||||
}
|
||||
LOG_DEBUG("SwapChain Present: %p", fnIDXGISwapChainPresent);
|
||||
|
||||
HookManager::install(fnIDXGISwapChainPresent, Present);
|
||||
HookManager::install(fnIDXGISwapChainPresent, Present_Hook);
|
||||
LOG_DEBUG("Initializing D3D11 hook: done.");
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <d3d12.h>
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
#include <cheat-base/events/event.hpp>
|
||||
@ -18,5 +20,6 @@ namespace backend
|
||||
public:
|
||||
inline static TEvent<ID3D11DeviceContext*> RenderEvent{};
|
||||
inline static TEvent<HWND, ID3D11Device*, ID3D11DeviceContext*, IDXGISwapChain*> InitializeEvent{};
|
||||
inline static TEvent<> FailedEvent{};
|
||||
};
|
||||
}
|
||||
|
515
cheat-base/src/cheat-base/render/backend/dx12-hook.cpp
Normal file
515
cheat-base/src/cheat-base/render/backend/dx12-hook.cpp
Normal file
@ -0,0 +1,515 @@
|
||||
#include <pch.h>
|
||||
#include "dx12-hook.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
|
||||
#include <cheat-base/HookManager.h>
|
||||
|
||||
#include <dxgi1_4.h>
|
||||
|
||||
#pragma comment(lib, "D3dcompiler.lib")
|
||||
#pragma comment(lib, "d3d12.lib")
|
||||
#pragma comment(lib, "winmm.lib")
|
||||
|
||||
// D3X HOOK DEFINITIONS
|
||||
typedef HRESULT(APIENTRY* IDXGISwapChainPresent)(IDXGISwapChain3* pSwapChain, UINT SyncInterval, UINT Flags);
|
||||
typedef void(APIENTRY* DrawInstanced)(ID3D12GraphicsCommandList* dCommandList, UINT VertexCountPerInstance, UINT InstanceCount, UINT StartVertexLocation, UINT StartInstanceLocation);
|
||||
typedef void(APIENTRY* DrawIndexedInstanced)(ID3D12GraphicsCommandList* dCommandList, UINT IndexCountPerInstance, UINT InstanceCount, UINT StartIndexLocation, INT BaseVertexLocation, UINT StartInstanceLocation);
|
||||
typedef void(APIENTRY* ExecuteCommandLists)(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists);
|
||||
|
||||
struct DirectX12MainFunctions
|
||||
{
|
||||
IDXGISwapChainPresent presentFunc;
|
||||
DrawInstanced drawInstancedFunc;
|
||||
DrawIndexedInstanced drawIndexedInstancedFunc;
|
||||
ExecuteCommandLists executeCommandListFunc;
|
||||
};
|
||||
|
||||
// Definition of WndProc Hook. Its here to avoid dragging dependencies on <windows.h> types.
|
||||
extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
namespace DirectX12Interface {
|
||||
ID3D12Device* Device = nullptr;
|
||||
ID3D12DescriptorHeap* DescriptorHeapBackBuffers;
|
||||
ID3D12DescriptorHeap* DescriptorHeapImGuiRender;
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
ID3D12CommandQueue* CommandQueue;
|
||||
|
||||
struct _FrameContext {
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
ID3D12Resource* Resource;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE DescriptorHandle;
|
||||
};
|
||||
|
||||
UINT BuffersCounts = -1;
|
||||
_FrameContext* FrameContext;
|
||||
}
|
||||
|
||||
static HRESULT __stdcall Present_Hook(IDXGISwapChain3* pChain, const UINT SyncInterval, const UINT Flags)
|
||||
{
|
||||
static BOOL g_bInitialised = false;
|
||||
|
||||
if (!g_bInitialised)
|
||||
{
|
||||
auto result = (HRESULT)pChain->GetDevice(__uuidof(DirectX12Interface::Device), reinterpret_cast<void**>(&DirectX12Interface::Device));
|
||||
LOG_DEBUG("Result of GetDevice: %x", HRESULT_CODE(result));
|
||||
|
||||
if (SUCCEEDED(result))
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC Desc;
|
||||
pChain->GetDesc(&Desc);
|
||||
Desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
Desc.Windowed = ((GetWindowLongPtr(Desc.OutputWindow, GWL_STYLE) & WS_POPUP) != 0) ? false : true;
|
||||
|
||||
DirectX12Interface::BuffersCounts = Desc.BufferCount;
|
||||
DirectX12Interface::FrameContext = new DirectX12Interface::_FrameContext[DirectX12Interface::BuffersCounts];
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC DescriptorImGuiRender = {};
|
||||
DescriptorImGuiRender.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
DescriptorImGuiRender.NumDescriptors = DirectX12Interface::BuffersCounts;
|
||||
DescriptorImGuiRender.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
|
||||
if (DirectX12Interface::Device->CreateDescriptorHeap(&DescriptorImGuiRender, IID_PPV_ARGS(&DirectX12Interface::DescriptorHeapImGuiRender)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
ID3D12CommandAllocator* Allocator;
|
||||
if (DirectX12Interface::Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&Allocator)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
for (size_t i = 0; i < DirectX12Interface::BuffersCounts; i++) {
|
||||
DirectX12Interface::FrameContext[i].CommandAllocator = Allocator;
|
||||
}
|
||||
|
||||
if (DirectX12Interface::Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, Allocator, NULL, IID_PPV_ARGS(&DirectX12Interface::CommandList)) != S_OK ||
|
||||
DirectX12Interface::CommandList->Close() != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
D3D12_DESCRIPTOR_HEAP_DESC DescriptorBackBuffers;
|
||||
DescriptorBackBuffers.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
DescriptorBackBuffers.NumDescriptors = DirectX12Interface::BuffersCounts;
|
||||
DescriptorBackBuffers.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
DescriptorBackBuffers.NodeMask = 1;
|
||||
|
||||
if (DirectX12Interface::Device->CreateDescriptorHeap(&DescriptorBackBuffers, IID_PPV_ARGS(&DirectX12Interface::DescriptorHeapBackBuffers)) != S_OK)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
const auto RTVDescriptorSize = DirectX12Interface::Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE RTVHandle = DirectX12Interface::DescriptorHeapBackBuffers->GetCPUDescriptorHandleForHeapStart();
|
||||
|
||||
for (size_t i = 0; i < DirectX12Interface::BuffersCounts; i++) {
|
||||
ID3D12Resource* pBackBuffer = nullptr;
|
||||
DirectX12Interface::FrameContext[i].DescriptorHandle = RTVHandle;
|
||||
pChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer));
|
||||
DirectX12Interface::Device->CreateRenderTargetView(pBackBuffer, nullptr, RTVHandle);
|
||||
DirectX12Interface::FrameContext[i].Resource = pBackBuffer;
|
||||
RTVHandle.ptr += RTVDescriptorSize;
|
||||
}
|
||||
|
||||
backend::DX12Events::InitializeEvent(Desc.OutputWindow, DirectX12Interface::Device, DirectX12Interface::BuffersCounts, DirectX12Interface::DescriptorHeapImGuiRender);
|
||||
|
||||
g_bInitialised = true;
|
||||
}
|
||||
}
|
||||
|
||||
// render function
|
||||
if (!g_bInitialised || DirectX12Interface::CommandQueue == nullptr)
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
|
||||
backend::DX12Events::PreRenderEvent();
|
||||
|
||||
DirectX12Interface::_FrameContext& CurrentFrameContext = DirectX12Interface::FrameContext[pChain->GetCurrentBackBufferIndex()];
|
||||
CurrentFrameContext.CommandAllocator->Reset();
|
||||
|
||||
D3D12_RESOURCE_BARRIER Barrier;
|
||||
Barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
Barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
Barrier.Transition.pResource = CurrentFrameContext.Resource;
|
||||
Barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT;
|
||||
Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
|
||||
DirectX12Interface::CommandList->Reset(CurrentFrameContext.CommandAllocator, nullptr);
|
||||
DirectX12Interface::CommandList->ResourceBarrier(1, &Barrier);
|
||||
DirectX12Interface::CommandList->OMSetRenderTargets(1, &CurrentFrameContext.DescriptorHandle, FALSE, nullptr);
|
||||
DirectX12Interface::CommandList->SetDescriptorHeaps(1, &DirectX12Interface::DescriptorHeapImGuiRender);
|
||||
|
||||
backend::DX12Events::PostRenderEvent(DirectX12Interface::CommandList);
|
||||
|
||||
Barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||
Barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT;
|
||||
DirectX12Interface::CommandList->ResourceBarrier(1, &Barrier);
|
||||
DirectX12Interface::CommandList->Close();
|
||||
DirectX12Interface::CommandQueue->ExecuteCommandLists(1, reinterpret_cast<ID3D12CommandList* const*>(&DirectX12Interface::CommandList));
|
||||
|
||||
return CALL_ORIGIN(Present_Hook, pChain, SyncInterval, Flags);
|
||||
}
|
||||
|
||||
void ExecuteCommandLists_Hook(ID3D12CommandQueue* queue, UINT NumCommandLists, ID3D12CommandList* ppCommandLists) {
|
||||
if (!DirectX12Interface::CommandQueue)
|
||||
DirectX12Interface::CommandQueue = queue;
|
||||
|
||||
CALL_ORIGIN(ExecuteCommandLists_Hook, queue, NumCommandLists, ppCommandLists);
|
||||
}
|
||||
|
||||
static void GetHardwareAdapter(IDXGIFactory4* pFactory, IDXGIAdapter1** ppAdapter)
|
||||
{
|
||||
*ppAdapter = nullptr;
|
||||
for (UINT adapterIndex = 0; ; ++adapterIndex)
|
||||
{
|
||||
IDXGIAdapter1* pAdapter = nullptr;
|
||||
if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))
|
||||
{
|
||||
// No more adapters to enumerate.
|
||||
break;
|
||||
}
|
||||
|
||||
// Check to see if the adapter supports Direct3D 12, but don't create the
|
||||
// actual device yet.
|
||||
if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))
|
||||
{
|
||||
*ppAdapter = pAdapter;
|
||||
return;
|
||||
}
|
||||
pAdapter->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
WNDCLASSEX WindowClass;
|
||||
HWND WindowHwnd;
|
||||
|
||||
bool InitWindow() {
|
||||
|
||||
WindowClass.cbSize = sizeof(WNDCLASSEX);
|
||||
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
WindowClass.lpfnWndProc = DefWindowProc;
|
||||
WindowClass.cbClsExtra = 0;
|
||||
WindowClass.cbWndExtra = 0;
|
||||
WindowClass.hInstance = GetModuleHandle(NULL);
|
||||
WindowClass.hIcon = NULL;
|
||||
WindowClass.hCursor = NULL;
|
||||
WindowClass.hbrBackground = NULL;
|
||||
WindowClass.lpszMenuName = NULL;
|
||||
WindowClass.lpszClassName = "MJ";
|
||||
WindowClass.hIconSm = NULL;
|
||||
RegisterClassEx(&WindowClass);
|
||||
WindowHwnd = CreateWindow(WindowClass.lpszClassName, "DirectX Window", WS_OVERLAPPEDWINDOW, 0, 0, 100, 100, NULL, NULL, WindowClass.hInstance, NULL);
|
||||
if (WindowHwnd == NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DeleteWindow() {
|
||||
DestroyWindow(WindowHwnd);
|
||||
UnregisterClass(WindowClass.lpszClassName, WindowClass.hInstance);
|
||||
if (WindowHwnd != NULL) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FindFunctions(DirectX12MainFunctions& mainFunctions) {
|
||||
|
||||
if (InitWindow() == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HMODULE D3D12Module = GetModuleHandle("d3d12.dll");
|
||||
HMODULE DXGIModule = GetModuleHandle("dxgi.dll");
|
||||
if (D3D12Module == NULL || DXGIModule == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
void* CreateDXGIFactory = GetProcAddress(DXGIModule, "CreateDXGIFactory");
|
||||
if (CreateDXGIFactory == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIFactory* Factory;
|
||||
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&Factory) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
IDXGIAdapter* Adapter;
|
||||
if (Factory->EnumAdapters(0, &Adapter) == DXGI_ERROR_NOT_FOUND) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
void* D3D12CreateDevice = GetProcAddress(D3D12Module, "D3D12CreateDevice");
|
||||
if (D3D12CreateDevice == NULL) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12Device* Device;
|
||||
if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(Adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&Device) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC QueueDesc;
|
||||
QueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
QueueDesc.Priority = 0;
|
||||
QueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
QueueDesc.NodeMask = 0;
|
||||
|
||||
ID3D12CommandQueue* CommandQueue;
|
||||
if (Device->CreateCommandQueue(&QueueDesc, __uuidof(ID3D12CommandQueue), (void**)&CommandQueue) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12CommandAllocator* CommandAllocator;
|
||||
if (Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&CommandAllocator) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList* CommandList;
|
||||
if (Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, CommandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&CommandList) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
DXGI_RATIONAL RefreshRate;
|
||||
RefreshRate.Numerator = 60;
|
||||
RefreshRate.Denominator = 1;
|
||||
|
||||
DXGI_MODE_DESC BufferDesc;
|
||||
BufferDesc.Width = 100;
|
||||
BufferDesc.Height = 100;
|
||||
BufferDesc.RefreshRate = RefreshRate;
|
||||
BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
||||
BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
DXGI_SAMPLE_DESC SampleDesc;
|
||||
SampleDesc.Count = 1;
|
||||
SampleDesc.Quality = 0;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC SwapChainDesc = {};
|
||||
SwapChainDesc.BufferDesc = BufferDesc;
|
||||
SwapChainDesc.SampleDesc = SampleDesc;
|
||||
SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
SwapChainDesc.BufferCount = 2;
|
||||
SwapChainDesc.OutputWindow = WindowHwnd;
|
||||
SwapChainDesc.Windowed = 1;
|
||||
SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
SwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
||||
|
||||
IDXGISwapChain* SwapChain;
|
||||
if (Factory->CreateSwapChain(CommandQueue, &SwapChainDesc, &SwapChain) < 0) {
|
||||
DeleteWindow();
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef uint64_t uintx_t;
|
||||
auto MethodsTable = (uintx_t*)::calloc(150, sizeof(uintx_t));
|
||||
memcpy(MethodsTable, *(uintx_t**)Device, 44 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44, *(uintx_t**)CommandQueue, 19 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19, *(uintx_t**)CommandAllocator, 9 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19 + 9, *(uintx_t**)CommandList, 60 * sizeof(uintx_t));
|
||||
memcpy(MethodsTable + 44 + 19 + 9 + 60, *(uintx_t**)SwapChain, 18 * sizeof(uintx_t));
|
||||
|
||||
mainFunctions.presentFunc = reinterpret_cast<decltype(mainFunctions.presentFunc)>(MethodsTable[140]);
|
||||
mainFunctions.drawInstancedFunc = reinterpret_cast<decltype(mainFunctions.drawInstancedFunc)>(MethodsTable[84]);
|
||||
mainFunctions.drawIndexedInstancedFunc = reinterpret_cast<decltype(mainFunctions.drawIndexedInstancedFunc)>(MethodsTable[85]);
|
||||
mainFunctions.executeCommandListFunc = reinterpret_cast<decltype(mainFunctions.executeCommandListFunc)>(MethodsTable[54]);
|
||||
|
||||
free(MethodsTable);
|
||||
|
||||
Device->Release();
|
||||
Device = NULL;
|
||||
CommandQueue->Release();
|
||||
CommandQueue = NULL;
|
||||
CommandAllocator->Release();
|
||||
CommandAllocator = NULL;
|
||||
CommandList->Release();
|
||||
CommandList = NULL;
|
||||
SwapChain->Release();
|
||||
SwapChain = NULL;
|
||||
DeleteWindow();
|
||||
return true;
|
||||
}
|
||||
|
||||
void backend::InitializeDX12Hooks()
|
||||
{
|
||||
LOG_DEBUG("Initializing D3D12 hook: started.");
|
||||
|
||||
DirectX12MainFunctions mainFuncs;
|
||||
if (!FindFunctions(mainFuncs))
|
||||
{
|
||||
LOG_ERROR("Failed to find 'Present' function for D3D12.");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("IDXGISwapChainPresent Present: %p", mainFuncs.presentFunc);
|
||||
LOG_DEBUG("DrawInstanced Present: %p", mainFuncs.drawInstancedFunc);
|
||||
LOG_DEBUG("DrawIndexedInstanced Present: %p", mainFuncs.drawIndexedInstancedFunc);
|
||||
LOG_DEBUG("ExecuteCommandLists Present: %p", mainFuncs.executeCommandListFunc);
|
||||
|
||||
HookManager::install(mainFuncs.presentFunc, Present_Hook);
|
||||
HookManager::install(mainFuncs.executeCommandListFunc, ExecuteCommandLists_Hook);
|
||||
|
||||
LOG_DEBUG("Initializing D3D12 hook: done.");
|
||||
}
|
||||
|
||||
bool backend::LoadTextureFromMemory(LPBYTE image_data, int image_width, int image_height, D3D12_CPU_DESCRIPTOR_HANDLE srv_cpu_handle,
|
||||
ID3D12Resource** out_tex_resource, int* out_width, int* out_height)
|
||||
{
|
||||
if (DirectX12Interface::Device == nullptr)
|
||||
return false;
|
||||
|
||||
// Create texture resource
|
||||
D3D12_HEAP_PROPERTIES props;
|
||||
memset(&props, 0, sizeof(D3D12_HEAP_PROPERTIES));
|
||||
props.Type = D3D12_HEAP_TYPE_DEFAULT;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
ZeroMemory(&desc, sizeof(desc));
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = image_width;
|
||||
desc.Height = image_height;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
ID3D12Resource* pTexture = NULL;
|
||||
DirectX12Interface::Device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&pTexture));
|
||||
|
||||
// Create a temporary upload resource to move the data in
|
||||
UINT uploadPitch = (image_width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
|
||||
UINT uploadSize = image_height * uploadPitch;
|
||||
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
|
||||
desc.Alignment = 0;
|
||||
desc.Width = uploadSize;
|
||||
desc.Height = 1;
|
||||
desc.DepthOrArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Format = DXGI_FORMAT_UNKNOWN;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
|
||||
desc.Flags = D3D12_RESOURCE_FLAG_NONE;
|
||||
|
||||
props.Type = D3D12_HEAP_TYPE_UPLOAD;
|
||||
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
|
||||
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
|
||||
|
||||
ID3D12Resource* uploadBuffer = NULL;
|
||||
HRESULT hr = DirectX12Interface::Device->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Write pixels into the upload resource
|
||||
void* mapped = NULL;
|
||||
D3D12_RANGE range = { 0, uploadSize };
|
||||
hr = uploadBuffer->Map(0, &range, &mapped);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
for (int y = 0; y < image_height; y++)
|
||||
memcpy((void*)((uintptr_t)mapped + y * uploadPitch), image_data + y * image_width * 4, image_width * 4);
|
||||
uploadBuffer->Unmap(0, &range);
|
||||
|
||||
// Copy the upload resource content into the real resource
|
||||
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
|
||||
srcLocation.pResource = uploadBuffer;
|
||||
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
|
||||
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srcLocation.PlacedFootprint.Footprint.Width = image_width;
|
||||
srcLocation.PlacedFootprint.Footprint.Height = image_height;
|
||||
srcLocation.PlacedFootprint.Footprint.Depth = 1;
|
||||
srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch;
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
|
||||
dstLocation.pResource = pTexture;
|
||||
dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
|
||||
dstLocation.SubresourceIndex = 0;
|
||||
|
||||
D3D12_RESOURCE_BARRIER barrier = {};
|
||||
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
|
||||
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
|
||||
barrier.Transition.pResource = pTexture;
|
||||
barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
|
||||
barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE;
|
||||
|
||||
// Create a temporary command queue to do the copy with
|
||||
ID3D12Fence* fence = NULL;
|
||||
hr = DirectX12Interface::Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
HANDLE event = CreateEvent(0, 0, 0, 0);
|
||||
IM_ASSERT(event != NULL);
|
||||
|
||||
D3D12_COMMAND_QUEUE_DESC queueDesc = {};
|
||||
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
||||
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
||||
queueDesc.NodeMask = 1;
|
||||
|
||||
ID3D12CommandQueue* cmdQueue = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12CommandAllocator* cmdAlloc = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
ID3D12GraphicsCommandList* cmdList = NULL;
|
||||
hr = DirectX12Interface::Device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList));
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL);
|
||||
cmdList->ResourceBarrier(1, &barrier);
|
||||
|
||||
hr = cmdList->Close();
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Execute the copy
|
||||
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
|
||||
hr = cmdQueue->Signal(fence, 1);
|
||||
IM_ASSERT(SUCCEEDED(hr));
|
||||
|
||||
// Wait for everything to complete
|
||||
fence->SetEventOnCompletion(1, event);
|
||||
WaitForSingleObject(event, INFINITE);
|
||||
|
||||
// Tear down our temporary command queue and release the upload resource
|
||||
cmdList->Release();
|
||||
cmdAlloc->Release();
|
||||
cmdQueue->Release();
|
||||
CloseHandle(event);
|
||||
fence->Release();
|
||||
uploadBuffer->Release();
|
||||
|
||||
// Create a shader resource view for the texture
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
ZeroMemory(&srvDesc, sizeof(srvDesc));
|
||||
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
srvDesc.Texture2D.MipLevels = desc.MipLevels;
|
||||
srvDesc.Texture2D.MostDetailedMip = 0;
|
||||
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
DirectX12Interface::Device->CreateShaderResourceView(pTexture, &srvDesc, srv_cpu_handle);
|
||||
|
||||
// Return results
|
||||
*out_tex_resource = pTexture;
|
||||
*out_width = image_width;
|
||||
*out_height = image_height;
|
||||
|
||||
return true;
|
||||
}
|
27
cheat-base/src/cheat-base/render/backend/dx12-hook.h
Normal file
27
cheat-base/src/cheat-base/render/backend/dx12-hook.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
#include <d3d12.h>
|
||||
|
||||
#include <d3dcompiler.h>
|
||||
|
||||
#include <cheat-base/events/event.hpp>
|
||||
|
||||
namespace backend
|
||||
{
|
||||
void InitializeDX12Hooks();
|
||||
|
||||
// Thanks to https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples#example-for-directx11-users
|
||||
bool LoadTextureFromMemory(LPBYTE image_data, int image_width, int image_height, D3D12_CPU_DESCRIPTOR_HANDLE srv_cpu_handle,
|
||||
ID3D12Resource** out_tex_resource, int* out_width, int* out_height);
|
||||
|
||||
class DX12Events
|
||||
{
|
||||
public:
|
||||
inline static TEvent<> PreRenderEvent{};
|
||||
inline static TEvent<ID3D12GraphicsCommandList*> PostRenderEvent{};
|
||||
inline static TEvent<HWND, ID3D12Device*, UINT, ID3D12DescriptorHeap*> InitializeEvent{};
|
||||
};
|
||||
|
||||
|
||||
}
|
@ -2,10 +2,15 @@
|
||||
#include "renderer.h"
|
||||
|
||||
#include <backends/imgui_impl_dx11.h>
|
||||
#pragma comment(lib, "dxgi")
|
||||
#include <backends/imgui_impl_dx12.h>
|
||||
|
||||
#include <backends/imgui_impl_win32.h>
|
||||
|
||||
#include <cheat-base/util.h>
|
||||
#include <cheat-base/render/backend/dx11-hook.h>
|
||||
#include <cheat-base/render/backend/dx12-hook.h>
|
||||
|
||||
#include <cheat-base/ResourceLoader.h>
|
||||
|
||||
extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
||||
@ -33,19 +38,39 @@ namespace renderer
|
||||
static WNDPROC OriginalWndProcHandler;
|
||||
static ID3D11RenderTargetView* mainRenderTargetView;
|
||||
|
||||
static void OnRender(ID3D11DeviceContext* pContext);
|
||||
static void OnDX11Initialize(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain);
|
||||
static void OnRenderDX11(ID3D11DeviceContext* pContext);
|
||||
static void OnInitializeDX11(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain);
|
||||
|
||||
void Init(LPBYTE fontData, DWORD fontDataSize)
|
||||
static void OnPreRenderDX12();
|
||||
static void OnPostRenderDX12(ID3D12GraphicsCommandList* commandList);
|
||||
static void OnInitializeDX12(HWND window, ID3D12Device* pDevice, UINT buffersCounts, ID3D12DescriptorHeap* pDescriptorHeapImGuiRender);
|
||||
|
||||
|
||||
|
||||
void Init(LPBYTE fontData, DWORD fontDataSize, DXVersion version)
|
||||
{
|
||||
_customFontData = { fontData, fontDataSize };
|
||||
|
||||
LOG_DEBUG("Initialize IMGui...");
|
||||
|
||||
backend::DX11Events::RenderEvent += FUNCTION_HANDLER(OnRender);
|
||||
backend::DX11Events::InitializeEvent += FUNCTION_HANDLER(OnDX11Initialize);
|
||||
|
||||
switch (version)
|
||||
{
|
||||
case renderer::DXVersion::D3D11:
|
||||
backend::DX11Events::RenderEvent += FUNCTION_HANDLER(OnRenderDX11);
|
||||
backend::DX11Events::InitializeEvent += FUNCTION_HANDLER(OnInitializeDX11);
|
||||
backend::InitializeDX11Hooks();
|
||||
break;
|
||||
case renderer::DXVersion::D3D12:
|
||||
backend::DX12Events::InitializeEvent += FUNCTION_HANDLER(OnInitializeDX12);
|
||||
backend::DX12Events::PreRenderEvent += FUNCTION_HANDLER(OnPreRenderDX12);
|
||||
backend::DX12Events::PostRenderEvent += FUNCTION_HANDLER(OnPostRenderDX12);
|
||||
backend::InitializeDX12Hooks();
|
||||
break;
|
||||
case renderer::DXVersion::D3D9:
|
||||
case renderer::DXVersion::D3D10:
|
||||
default:
|
||||
LOG_ERROR("Used unsupported version of DX.");
|
||||
}
|
||||
}
|
||||
|
||||
void SetInputLock(void* id, bool value)
|
||||
@ -134,7 +159,53 @@ namespace renderer
|
||||
static void SetupImGuiStyle();
|
||||
static LRESULT CALLBACK hWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
static void OnDX11Initialize(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain)
|
||||
void OnPreRenderDX12()
|
||||
{
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.FontDefault = GetFontBySize(_globalFontSize);
|
||||
ImGui::NewFrame();
|
||||
|
||||
events::RenderEvent();
|
||||
|
||||
ImGui::EndFrame();
|
||||
}
|
||||
|
||||
void OnPostRenderDX12(ID3D12GraphicsCommandList* commandList)
|
||||
{
|
||||
ImGui::Render();
|
||||
ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData(), commandList);
|
||||
}
|
||||
|
||||
void OnInitializeDX12(HWND window, ID3D12Device* pDevice, UINT buffersCounts, ID3D12DescriptorHeap* pDescriptorHeapImGuiRender)
|
||||
{
|
||||
LOG_DEBUG("ImGUI: DirectX12 backend initialized successfully.");
|
||||
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
|
||||
LoadCustomFont();
|
||||
SetupImGuiStyle();
|
||||
|
||||
//Set OriginalWndProcHandler to the Address of the Original WndProc function
|
||||
OriginalWndProcHandler = reinterpret_cast<WNDPROC>(SetWindowLongPtr(window, GWLP_WNDPROC,
|
||||
reinterpret_cast<LONG_PTR>(hWndProc)));
|
||||
|
||||
ImGui_ImplWin32_Init(window);
|
||||
ImGui_ImplDX12_Init(pDevice, buffersCounts, DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
pDescriptorHeapImGuiRender,
|
||||
pDescriptorHeapImGuiRender->GetCPUDescriptorHandleForHeapStart(),
|
||||
pDescriptorHeapImGuiRender->GetGPUDescriptorHandleForHeapStart());
|
||||
|
||||
ImGui_ImplDX12_CreateDeviceObjects();
|
||||
ImGui::GetIO().ImeWindowHandle = window;
|
||||
io.SetPlatformImeDataFn = nullptr; // F**king bug take 4 hours of my life
|
||||
}
|
||||
|
||||
static void OnInitializeDX11(HWND window, ID3D11Device* pDevice, ID3D11DeviceContext* pContext, IDXGISwapChain* pChain)
|
||||
{
|
||||
|
||||
LOG_DEBUG("ImGUI: DirectX11 backend initialized successfully.");
|
||||
@ -161,7 +232,7 @@ namespace renderer
|
||||
io.SetPlatformImeDataFn = nullptr; // F**king bug take 4 hours of my life
|
||||
}
|
||||
|
||||
static void OnRender(ID3D11DeviceContext* pContext)
|
||||
static void OnRenderDX11(ID3D11DeviceContext* pContext)
|
||||
{
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
ImGui_ImplWin32_NewFrame();
|
||||
|
@ -5,7 +5,15 @@
|
||||
|
||||
namespace renderer
|
||||
{
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize);
|
||||
enum class DXVersion
|
||||
{
|
||||
D3D9,
|
||||
D3D10,
|
||||
D3D11,
|
||||
D3D12
|
||||
};
|
||||
|
||||
void Init(LPBYTE pFontData, DWORD dFontDataSize, DXVersion version = DXVersion::D3D11);
|
||||
|
||||
// Font sizing
|
||||
ImFont* GetFontBySize(float fontSize);
|
||||
|
@ -272,6 +272,18 @@ namespace util
|
||||
return static_cast<int64_t>(timezoneInfo.Bias) * 60;
|
||||
}
|
||||
|
||||
void OpenConsole()
|
||||
{
|
||||
AllocConsole();
|
||||
freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
|
||||
freopen_s((FILE**)stderr, "CONOUT$", "w", stderr);
|
||||
|
||||
auto consoleWindow = GetConsoleWindow();
|
||||
SetForegroundWindow(consoleWindow);
|
||||
ShowWindow(consoleWindow, SW_RESTORE);
|
||||
ShowWindow(consoleWindow, SW_SHOW);
|
||||
}
|
||||
|
||||
void OpenURL(const char* url)
|
||||
{
|
||||
ShellExecute(nullptr, nullptr, url, nullptr, nullptr, SW_SHOW);
|
||||
|
@ -45,6 +45,7 @@ namespace util
|
||||
|
||||
int64_t GetTimezoneBias();
|
||||
|
||||
void OpenConsole();
|
||||
|
||||
template<typename ... Args>
|
||||
std::string string_format(const std::string& format, Args ... args)
|
||||
|
@ -15,6 +15,11 @@
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.h" />
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.h" />
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.h" />
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeClient.h" />
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeIO.h" />
|
||||
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h" />
|
||||
<ClInclude Include="src\user\cheat\world\FakeTime.h" />
|
||||
<ClInclude Include="src\user\cheat\debugger.h">
|
||||
@ -22,26 +27,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\MessageManager.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageBase.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageHeader.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\ModifyData.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\PacketData.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\GenshinCM.h" />
|
||||
<ClInclude Include="src\user\cheat\teleport\CustomTeleports.h" />
|
||||
<ClInclude Include="src\user\cheat\visuals\Browser.h" />
|
||||
@ -117,6 +102,11 @@
|
||||
<Font Include="res\Ruda-ExtraBold.ttf" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.cpp" />
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.cpp" />
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.cpp" />
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeClient.cpp" />
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeIO.cpp" />
|
||||
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp" />
|
||||
<ClCompile Include="src\user\cheat\world\FakeTime.cpp" />
|
||||
<ClCompile Include="src\user\cheat\debugger.cpp">
|
||||
@ -124,26 +114,6 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\MessageManager.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageBase.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageHeader.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\ModifyData.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\PacketData.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release_WS|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\teleport\CustomTeleports.cpp" />
|
||||
<ClCompile Include="src\user\cheat\GenshinCM.cpp" />
|
||||
<ClCompile Include="src\user\cheat\visuals\Browser.cpp" />
|
||||
@ -849,9 +819,11 @@
|
||||
<TargetName>CLibrary</TargetName>
|
||||
<OutDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\</OutDir>
|
||||
<IntDir>$(SolutionDir)bin\$(Configuration)-$(PlatformShortName)\obj\$(ProjectName)\</IntDir>
|
||||
<CustomBuildBeforeTargets>Run</CustomBuildBeforeTargets>
|
||||
<CustomBuildBeforeTargets>
|
||||
</CustomBuildBeforeTargets>
|
||||
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
|
||||
<CustomBuildAfterTargets>FinalizeBuildStatus</CustomBuildAfterTargets>
|
||||
<CustomBuildAfterTargets>
|
||||
</CustomBuildAfterTargets>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
|
@ -189,21 +189,6 @@
|
||||
<ClInclude Include="src\user\cheat\visuals\CameraZoom.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\MessageHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\ModifyData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\messages\PacketData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\MessageManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\debugger.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -237,6 +222,21 @@
|
||||
<ClInclude Include="src\user\cheat\visuals\TextureChanger.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeClient.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\user\cheat\misc\sniffer\pipe\PipeIO.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Font Include="res\Ruda-Bold.ttf" />
|
||||
@ -384,21 +384,6 @@
|
||||
<ClCompile Include="src\user\cheat\visuals\CameraZoom.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\MessageHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\ModifyData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\messages\PacketData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\MessageManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\visuals\ShowChestIndicator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -432,6 +417,21 @@
|
||||
<ClCompile Include="src\user\cheat\visuals\TextureChanger.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeMessage.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipeModifyData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\messages\PipePacketData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeClient.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\user\cheat\misc\sniffer\pipe\PipeIO.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="res\res.rc">
|
||||
|
@ -111,7 +111,7 @@ namespace cheat
|
||||
FEAT_INST(HideUI),
|
||||
FEAT_INST(Browser),
|
||||
FEAT_INST(EnablePeaking),
|
||||
FEAT_INST(TextureChanger),
|
||||
FEAT_INST(TextureChanger)
|
||||
|
||||
});
|
||||
#undef FEAT_INST
|
||||
|
@ -1,85 +0,0 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "MessageManager.h"
|
||||
|
||||
namespace sniffer
|
||||
{
|
||||
|
||||
void MessageManager::Send(MessageBase& data)
|
||||
{
|
||||
if (!IsConnected())
|
||||
return;
|
||||
|
||||
s_Pipe->WriteObject(data.header());
|
||||
s_Pipe->WriteObject(data);
|
||||
}
|
||||
|
||||
MessageBase* MessageManager::ReceiveMessage()
|
||||
{
|
||||
if (!IsConnected())
|
||||
return nullptr;
|
||||
|
||||
MessageHeader header;
|
||||
s_Pipe->ReadObject(header);
|
||||
|
||||
MessageIDs messageID = static_cast<MessageIDs>(header.messageID());
|
||||
|
||||
#define MESSAGE_CASE(mid, type)\
|
||||
case mid: \
|
||||
{ \
|
||||
auto data = new type(header); \
|
||||
s_Pipe->ReadObject(*data); \
|
||||
CallHandlers(*data); \
|
||||
return reinterpret_cast<MessageBase*>(data);\
|
||||
}
|
||||
|
||||
switch (messageID)
|
||||
{
|
||||
MESSAGE_CASE(MessageIDs::PACKET_DATA, PacketData);
|
||||
MESSAGE_CASE(MessageIDs::MODIFY_DATA, ModifyData);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MessageManager::ProcessMessage()
|
||||
{
|
||||
delete ReceiveMessage();
|
||||
}
|
||||
|
||||
bool MessageManager::IsConnected()
|
||||
{
|
||||
if (s_Pipe == nullptr)
|
||||
return false;
|
||||
|
||||
return s_Pipe->IsPipeOpened() || TryConnectToPipe();
|
||||
}
|
||||
|
||||
void MessageManager::SetConnectionDelay(uint32_t delay)
|
||||
{
|
||||
s_ConnectionDelay = delay;
|
||||
}
|
||||
|
||||
uint32_t MessageManager::GetConnectionDelay()
|
||||
{
|
||||
return s_ConnectionDelay;
|
||||
}
|
||||
|
||||
void MessageManager::Connect(const std::string& pipeName)
|
||||
{
|
||||
if (s_Pipe != nullptr)
|
||||
delete s_Pipe;
|
||||
|
||||
s_Pipe = new PipeTransfer(pipeName);
|
||||
TryConnectToPipe();
|
||||
}
|
||||
|
||||
void MessageManager::Disconnect()
|
||||
{
|
||||
if (s_Pipe == nullptr)
|
||||
return;
|
||||
|
||||
delete s_Pipe;
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
#pragma once
|
||||
#include "messages/MessageHeader.h"
|
||||
#include "messages/ModifyData.h"
|
||||
#include "messages/PacketData.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace sniffer
|
||||
{
|
||||
enum MessageIDs : uint32_t
|
||||
{
|
||||
NONE = 0,
|
||||
PACKET_DATA = 1,
|
||||
MODIFY_DATA = 2
|
||||
};
|
||||
|
||||
class MessageManager
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
using CallbackFunction = void(*)(const T& packetData);
|
||||
|
||||
template<class T>
|
||||
inline static void AddHandler(CallbackFunction<T> callback)
|
||||
{
|
||||
s_Handlers.push_back(callback);
|
||||
}
|
||||
|
||||
template<class TMessage>
|
||||
inline static TMessage CreateMessage(uint32_t reqID = 0)
|
||||
{
|
||||
static_assert(std::is_base_of<MessageBase, TMessage>::value, "Should be derived of MessageBase.");
|
||||
|
||||
return TMessage(MessageHeader{ GetMessageIDByType<TMessage>(), reqID });
|
||||
}
|
||||
|
||||
template<class TMessage>
|
||||
inline static std::optional<TMessage> WaitFor()
|
||||
{
|
||||
static_assert(std::is_base_of<MessageBase, TMessage>::value, "Should be derived of MessageBase.");
|
||||
|
||||
if (!IsConnected())
|
||||
return {};
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto messagePtr = ReceiveMessage();
|
||||
if (messagePtr == nullptr)
|
||||
return {};
|
||||
|
||||
if (GetMessageIDByType<TMessage>() != messagePtr->messageID())
|
||||
{
|
||||
delete messagePtr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copying message
|
||||
TMessage message = *reinterpret_cast<TMessage*>(messagePtr);
|
||||
delete messagePtr;
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
static void Send(MessageBase& data);
|
||||
|
||||
static MessageBase* ReceiveMessage();
|
||||
|
||||
static void ProcessMessage();
|
||||
|
||||
static void SetConnectionDelay(uint32_t delay);
|
||||
|
||||
static uint32_t GetConnectionDelay();
|
||||
|
||||
static bool IsConnected();
|
||||
|
||||
static void Connect(const std::string& pipeName);
|
||||
|
||||
static void Disconnect();
|
||||
|
||||
private:
|
||||
|
||||
inline static PipeTransfer* s_Pipe = nullptr;
|
||||
|
||||
inline static uint32_t s_ConnectionDelay = 5;
|
||||
inline static std::time_t s_NextTimeToConnect = 0;
|
||||
|
||||
template<class T>
|
||||
static std::vector<CallbackFunction<T>> s_Handlers;
|
||||
|
||||
static bool TryConnectToPipe()
|
||||
{
|
||||
if (s_Pipe == nullptr)
|
||||
return false;
|
||||
|
||||
std::time_t currTime = std::time(0);
|
||||
if (s_NextTimeToConnect > currTime)
|
||||
return false;
|
||||
|
||||
bool result = s_Pipe->Connect();
|
||||
if (result)
|
||||
LOG_INFO("Connected to pipe successfully.");
|
||||
else
|
||||
s_NextTimeToConnect = currTime + 5; // delay in 5 sec
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class TMessage> static uint32_t GetMessageIDByType();
|
||||
template<> static uint32_t GetMessageIDByType<PacketData>() { return MessageIDs::PACKET_DATA; }
|
||||
template<> static uint32_t GetMessageIDByType<ModifyData>() { return MessageIDs::MODIFY_DATA; }
|
||||
|
||||
template<class T>
|
||||
static void CallHandlers(const T& message)
|
||||
{
|
||||
for (auto& handler : s_Handlers<T>)
|
||||
handler(message);
|
||||
}
|
||||
};
|
||||
}
|
@ -16,7 +16,7 @@ namespace cheat::feature
|
||||
NF(f_PipeName, "Pipe name", "PacketSniffer", "genshin_packet_pipe")
|
||||
|
||||
{
|
||||
sniffer::MessageManager::Connect(f_PipeName.value());
|
||||
client.Connect(f_PipeName.value());
|
||||
|
||||
HookManager::install(app::Kcp_KcpNative_kcp_client_send_packet, KcpNative_kcp_client_send_packet_Hook);
|
||||
HookManager::install(app::MoleMole_KcpClient_TryDequeueEvent, KcpClient_TryDequeueEvent_Hook);
|
||||
@ -42,36 +42,36 @@ namespace cheat::feature
|
||||
return instance;
|
||||
}
|
||||
|
||||
bool PacketSniffer::ProcessModifiedData(app::KcpPacket_1* packet)
|
||||
bool PacketSniffer::ProcessModifiedData(app::KcpPacket_1*& packet)
|
||||
{
|
||||
auto modify_data = sniffer::MessageManager::WaitFor<ModifyData>();
|
||||
auto modify_data = client.WaitFor<PipeModifyData>();
|
||||
if (!modify_data)
|
||||
return false;
|
||||
|
||||
switch (modify_data->modify_type)
|
||||
switch (modify_data->modifyType)
|
||||
{
|
||||
case PacketModifyType::Blocked:
|
||||
case ModifyType::Blocked:
|
||||
return true;
|
||||
|
||||
case PacketModifyType::Modified:
|
||||
case ModifyType::Modified:
|
||||
{
|
||||
auto data_size = modify_data->modified_head.size() + modify_data->modified_message.size() + 12;
|
||||
auto data_size = modify_data->head.size() + modify_data->content.size() + 12;
|
||||
char* data = new char[data_size];
|
||||
|
||||
auto head_size = static_cast<uint16_t>(modify_data->modified_head.size());
|
||||
auto message_size = static_cast<uint32_t>(modify_data->modified_message.size());
|
||||
auto head_size = static_cast<uint16_t>(modify_data->head.size());
|
||||
auto message_size = static_cast<uint32_t>(modify_data->content.size());
|
||||
|
||||
util::WriteMapped(data, 0, static_cast<uint16_t>(0x4567)); // Magic number
|
||||
util::WriteMapped(data, 2, modify_data->message_id); // Message id
|
||||
util::WriteMapped(data, 2, modify_data->messageID); // Message id
|
||||
util::WriteMapped(data, 4, head_size); // Head size
|
||||
util::WriteMapped(data, 6, message_size); // Message size
|
||||
|
||||
// Fill content
|
||||
char* ptr_head_content = data + 10;
|
||||
memcpy_s(ptr_head_content, head_size, modify_data->modified_head.data(), head_size);
|
||||
memcpy_s(ptr_head_content, head_size, modify_data->head.data(), head_size);
|
||||
|
||||
char* ptr_message_content = ptr_head_content + modify_data->modified_head.size();
|
||||
memcpy_s(ptr_message_content, message_size, modify_data->modified_message.data(), message_size);
|
||||
char* ptr_message_content = ptr_head_content + modify_data->head.size();
|
||||
memcpy_s(ptr_message_content, message_size, modify_data->content.data(), message_size);
|
||||
|
||||
util::WriteMapped(ptr_message_content, message_size, static_cast<uint16_t>(0x89AB));
|
||||
|
||||
@ -86,28 +86,29 @@ namespace cheat::feature
|
||||
packet = new_packet;
|
||||
}
|
||||
break;
|
||||
case PacketModifyType::Unchanged:
|
||||
case ModifyType::Unchanged:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PacketSniffer::OnPacketIO(app::KcpPacket_1* packet, PacketIOType type)
|
||||
bool PacketSniffer::OnPacketIO(app::KcpPacket_1*& packet, NetIODirection direction)
|
||||
{
|
||||
if (!sniffer::MessageManager::IsConnected())
|
||||
if (!client.IsConnected())
|
||||
return true;
|
||||
|
||||
if (!f_CaptureEnabled)
|
||||
return true;
|
||||
|
||||
PacketData packetData = ParseRawPacketData((char*)packet->data, packet->dataLen);
|
||||
if (!packetData.valid)
|
||||
auto pipeData = client.CreateMessage<PipePacketData>();
|
||||
bool parsed = ParseRawPacketData((char*)packet->data, packet->dataLen, pipeData);
|
||||
if (!parsed)
|
||||
return true;
|
||||
|
||||
packetData.ioType = type;
|
||||
packetData.blockModeEnabled = f_ManipulationEnabled;
|
||||
sniffer::MessageManager::Send(packetData);
|
||||
pipeData.direction = direction;
|
||||
pipeData.manipulationEnabled = f_ManipulationEnabled;
|
||||
client.Send(pipeData);
|
||||
|
||||
bool canceled = f_ManipulationEnabled && ProcessModifiedData(packet);
|
||||
|
||||
@ -126,7 +127,7 @@ namespace cheat::feature
|
||||
delete[] byteArray;
|
||||
}
|
||||
|
||||
PacketData PacketSniffer::ParseRawPacketData(char* encryptedData, uint32_t length)
|
||||
bool PacketSniffer::ParseRawPacketData(char* encryptedData, uint32_t length, PipePacketData& dataOut)
|
||||
{
|
||||
// Packet structure
|
||||
// * Magic word (0x4567) [2 bytes]
|
||||
@ -139,7 +140,6 @@ namespace cheat::feature
|
||||
|
||||
// Header size - 12 bytes
|
||||
|
||||
PacketData packetData = sniffer::MessageManager::CreateMessage<PacketData>();
|
||||
// Decrypting packetData
|
||||
auto data = new char[length];
|
||||
memcpy_s(data, length, encryptedData, length);
|
||||
@ -150,14 +150,14 @@ namespace cheat::feature
|
||||
if (magicHead != 0x4567)
|
||||
{
|
||||
LOG_ERROR("Head magic value for packet is not valid.");
|
||||
return packetData;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t magicEnd = util::ReadMapped<uint16_t>(data, length - 2);
|
||||
if (magicEnd != 0x89AB)
|
||||
{
|
||||
LOG_ERROR("End magic value for packet is not valid.");
|
||||
return packetData;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t messageId = util::ReadMapped<uint16_t>(data, 2);
|
||||
@ -167,21 +167,20 @@ namespace cheat::feature
|
||||
if (length < headSize + contenSize + 12)
|
||||
{
|
||||
LOG_ERROR("Packet size is not valid.");
|
||||
return packetData;
|
||||
return false;
|
||||
}
|
||||
|
||||
packetData.valid = true;
|
||||
packetData.messageID = messageId;
|
||||
dataOut.messageID = messageId;
|
||||
|
||||
packetData.headRawData = std::vector<byte>((size_t)headSize, 0);
|
||||
memcpy_s(packetData.headRawData.data(), headSize, data + 10, headSize);
|
||||
dataOut.head = std::vector<byte>((size_t)headSize, 0);
|
||||
memcpy_s(dataOut.head.data(), headSize, data + 10, headSize);
|
||||
|
||||
packetData.messageRawData = std::vector<byte>((size_t)contenSize, 0);
|
||||
memcpy_s(packetData.messageRawData.data(), contenSize, data + 10 + headSize, contenSize);
|
||||
dataOut.content = std::vector<byte>((size_t)contenSize, 0);
|
||||
memcpy_s(dataOut.content.data(), contenSize, data + 10 + headSize, contenSize);
|
||||
|
||||
delete[] data;
|
||||
|
||||
return packetData;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PacketSniffer::KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method)
|
||||
@ -193,13 +192,13 @@ namespace cheat::feature
|
||||
return result;
|
||||
|
||||
auto& sniffer = GetInstance();
|
||||
return sniffer.OnPacketIO(evt->_evt.packet, PacketIOType::Receive);
|
||||
return sniffer.OnPacketIO(evt->_evt.packet, NetIODirection::Receive);
|
||||
}
|
||||
|
||||
int32_t PacketSniffer::KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method)
|
||||
{
|
||||
auto& sniffer = GetInstance();
|
||||
if (!sniffer.OnPacketIO(packet, PacketIOType::Send))
|
||||
if (!sniffer.OnPacketIO(packet, NetIODirection::Send))
|
||||
return 0;
|
||||
|
||||
return CALL_ORIGIN(KcpNative_kcp_client_send_packet_Hook, kcp_client, packet, method);
|
||||
|
@ -7,10 +7,9 @@
|
||||
#include <cheat-base/config/config.h>
|
||||
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
#include "messages/PacketData.h"
|
||||
#include "messages/ModifyData.h"
|
||||
|
||||
#include "MessageManager.h"
|
||||
#include "pipe/messages/PipeModifyData.h"
|
||||
#include "pipe/messages/PipePacketData.h"
|
||||
#include "pipe/PipeClient.h"
|
||||
|
||||
namespace cheat::feature
|
||||
{
|
||||
@ -22,6 +21,8 @@ namespace cheat::feature
|
||||
config::Field<bool> f_ManipulationEnabled;
|
||||
config::Field<std::string> f_PipeName;
|
||||
|
||||
PipeClient client;
|
||||
|
||||
static PacketSniffer& GetInstance();
|
||||
|
||||
const FeatureGUIInfo& GetGUIInfo() const override;
|
||||
@ -30,13 +31,13 @@ namespace cheat::feature
|
||||
private:
|
||||
PacketSniffer();
|
||||
|
||||
bool ProcessModifiedData(app::KcpPacket_1* packet);
|
||||
PacketData ParseRawPacketData(char* encryptedData, uint32_t length);
|
||||
bool ProcessModifiedData(app::KcpPacket_1*& packet);
|
||||
bool ParseRawPacketData(char* encryptedData, uint32_t length, PipePacketData& dataOut);
|
||||
static void EncryptXor(void* content, uint32_t length);
|
||||
static bool KcpClient_TryDequeueEvent_Hook(void* __this, app::ClientKcpEvent* evt, MethodInfo* method);
|
||||
static int32_t KcpNative_kcp_client_send_packet_Hook(void* kcp_client, app::KcpPacket_1* packet, MethodInfo* method);
|
||||
|
||||
bool OnPacketIO(app::KcpPacket_1* packet, PacketIOType type);
|
||||
bool OnPacketIO(app::KcpPacket_1*& packet, NetIODirection direction);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "MessageBase.h"
|
||||
|
||||
MessageBase::MessageBase(const MessageHeader& header) : m_Header(header)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
uint32_t MessageBase::requestID() const
|
||||
{
|
||||
return m_Header.requestID();
|
||||
}
|
||||
|
||||
uint32_t MessageBase::messageID() const
|
||||
{
|
||||
return m_Header.messageID();
|
||||
}
|
||||
|
||||
int64_t MessageBase::timestamp() const
|
||||
{
|
||||
return m_Header.timestamp();
|
||||
}
|
||||
|
||||
uint64_t MessageBase::sequenceID() const
|
||||
{
|
||||
return m_Header.sequenceID();
|
||||
}
|
||||
|
||||
MessageHeader& MessageBase::header()
|
||||
{
|
||||
return m_Header;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "MessageHeader.h"
|
||||
class MessageBase : public PipeSerializedObject
|
||||
{
|
||||
public:
|
||||
explicit MessageBase(const MessageHeader& header);
|
||||
|
||||
uint32_t requestID() const;
|
||||
uint32_t messageID() const;
|
||||
int64_t timestamp() const;
|
||||
uint64_t sequenceID() const;
|
||||
|
||||
MessageHeader& header();
|
||||
private:
|
||||
MessageHeader m_Header;
|
||||
};
|
||||
|
@ -1,53 +0,0 @@
|
||||
#include <pch-il2cpp.h>
|
||||
#include "MessageHeader.h"
|
||||
|
||||
|
||||
MessageHeader::MessageHeader(uint32_t messageId, uint32_t requestID /*= 0*/) :
|
||||
m_MessageID(messageId), m_RequestID(requestID),
|
||||
m_SequenceID(GenerateSequenceID()), m_Timestamp(util::GetCurrentTimeMillisec())
|
||||
{ }
|
||||
|
||||
MessageHeader::MessageHeader() : m_MessageID(0), m_RequestID(0), m_SequenceID(0), m_Timestamp(0)
|
||||
{ }
|
||||
|
||||
uint32_t MessageHeader::requestID() const
|
||||
{
|
||||
return m_RequestID;
|
||||
}
|
||||
|
||||
uint32_t MessageHeader::messageID() const
|
||||
{
|
||||
return m_MessageID;
|
||||
}
|
||||
|
||||
int64_t MessageHeader::timestamp() const
|
||||
{
|
||||
return m_Timestamp;
|
||||
}
|
||||
|
||||
uint64_t MessageHeader::sequenceID() const
|
||||
{
|
||||
return m_SequenceID;
|
||||
}
|
||||
|
||||
void MessageHeader::Write(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Write(m_MessageID);
|
||||
transfer->Write(m_RequestID);
|
||||
transfer->Write(util::GetCurrentTimeMillisec());
|
||||
transfer->Write(m_SequenceID);
|
||||
}
|
||||
|
||||
void MessageHeader::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read(m_MessageID);
|
||||
transfer->Read(m_RequestID);
|
||||
transfer->Read(m_Timestamp);
|
||||
transfer->Read(m_SequenceID);
|
||||
}
|
||||
|
||||
uint64_t MessageHeader::GenerateSequenceID()
|
||||
{
|
||||
s_SequenceGlobalID += 1;
|
||||
return s_SequenceGlobalID;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#pragma once
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
|
||||
class MessageHeader : public PipeSerializedObject
|
||||
{
|
||||
public:
|
||||
MessageHeader();
|
||||
MessageHeader(uint32_t messageId, uint32_t requestID = 0);
|
||||
uint32_t requestID() const;
|
||||
uint32_t messageID() const;
|
||||
int64_t timestamp() const;
|
||||
uint64_t sequenceID() const;
|
||||
|
||||
void Write(PipeTransfer* transfer) final;
|
||||
void Read(PipeTransfer* transfer) final;
|
||||
|
||||
private:
|
||||
inline static std::atomic<uint64_t> s_SequenceGlobalID {};
|
||||
static uint64_t GenerateSequenceID();
|
||||
|
||||
uint32_t m_MessageID;
|
||||
uint32_t m_RequestID;
|
||||
int64_t m_Timestamp;
|
||||
int64_t m_SequenceID;
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
#include <pch-il2cpp.h>
|
||||
#include "ModifyData.h"
|
||||
|
||||
ModifyData::ModifyData(const MessageHeader& header) : MessageBase(header),
|
||||
modify_type(PacketModifyType::Unchanged)
|
||||
{ }
|
||||
|
||||
void ModifyData::Write(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Write<PacketModifyType>(modify_type);
|
||||
if (modify_type == PacketModifyType::Modified)
|
||||
{
|
||||
transfer->Write(message_id);
|
||||
transfer->Write(modified_head);
|
||||
transfer->Write(modified_message);
|
||||
}
|
||||
}
|
||||
|
||||
void ModifyData::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read<PacketModifyType>(modify_type);
|
||||
if (modify_type == PacketModifyType::Modified)
|
||||
{
|
||||
transfer->Read(message_id);
|
||||
transfer->Read(modified_head);
|
||||
transfer->Read(modified_message);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
#include "MessageBase.h"
|
||||
|
||||
enum class PacketModifyType
|
||||
{
|
||||
Unchanged,
|
||||
Modified,
|
||||
Blocked
|
||||
};
|
||||
|
||||
class ModifyData : public MessageBase
|
||||
{
|
||||
public:
|
||||
PacketModifyType modify_type;
|
||||
|
||||
uint16_t message_id;
|
||||
std::string modified_head;
|
||||
std::string modified_message;
|
||||
|
||||
ModifyData(const MessageHeader& header);
|
||||
~ModifyData() {}
|
||||
|
||||
// Inherited via PipeSerializedObject
|
||||
void Write(PipeTransfer* transfer) override;
|
||||
void Read(PipeTransfer* transfer) override;
|
||||
};
|
||||
|
@ -1,20 +0,0 @@
|
||||
#include <pch-il2cpp.h>
|
||||
#include "PacketData.h"
|
||||
|
||||
void PacketData::Write(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Write(blockModeEnabled);
|
||||
transfer->Write(ioType);
|
||||
transfer->Write(messageID);
|
||||
transfer->Write(headRawData);
|
||||
transfer->Write(messageRawData);
|
||||
}
|
||||
|
||||
void PacketData::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read(blockModeEnabled);
|
||||
transfer->Read(ioType);
|
||||
transfer->Read(messageID);
|
||||
transfer->Read(headRawData);
|
||||
transfer->Read(messageRawData);
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
#include "MessageBase.h"
|
||||
|
||||
enum class PacketIOType
|
||||
{
|
||||
Receive,
|
||||
Send
|
||||
};
|
||||
|
||||
enum class PacketDataType
|
||||
{
|
||||
Raw,
|
||||
Parsed
|
||||
};
|
||||
|
||||
class PacketData : public MessageBase
|
||||
{
|
||||
public:
|
||||
using MessageBase::MessageBase;
|
||||
|
||||
bool blockModeEnabled;
|
||||
|
||||
PacketIOType ioType;
|
||||
PacketDataType dataType;
|
||||
|
||||
bool valid;
|
||||
|
||||
uint64_t parentPacketID;
|
||||
|
||||
int16_t messageID;
|
||||
std::vector<byte> headRawData;
|
||||
std::vector<byte> messageRawData;
|
||||
|
||||
std::string name;
|
||||
std::string headJson;
|
||||
std::string messageJson;
|
||||
|
||||
// Inherited via PipeSerializedObject
|
||||
virtual void Write(PipeTransfer* transfer) override;
|
||||
virtual void Read(PipeTransfer* transfer) override;
|
||||
};
|
@ -0,0 +1,54 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "PipeClient.h"
|
||||
|
||||
bool PipeClient::IsConnected()
|
||||
{
|
||||
if (m_Pipe == nullptr)
|
||||
return false;
|
||||
|
||||
return m_Pipe->IsPipeOpened() || TryConnectToPipe();
|
||||
}
|
||||
|
||||
void PipeClient::SetConnectionDelay(uint32_t delay)
|
||||
{
|
||||
m_ConnectionDelay = delay;
|
||||
}
|
||||
|
||||
uint32_t PipeClient::GetConnectionDelay()
|
||||
{
|
||||
return m_ConnectionDelay;
|
||||
}
|
||||
|
||||
void PipeClient::Connect(const std::string& pipeName)
|
||||
{
|
||||
if (m_Pipe != nullptr)
|
||||
delete m_Pipe;
|
||||
|
||||
m_Pipe = new PipeTransfer(pipeName);
|
||||
TryConnectToPipe();
|
||||
}
|
||||
|
||||
void PipeClient::Disconnect()
|
||||
{
|
||||
if (m_Pipe == nullptr)
|
||||
return;
|
||||
|
||||
delete m_Pipe;
|
||||
}
|
||||
|
||||
bool PipeClient::TryConnectToPipe()
|
||||
{
|
||||
if (m_Pipe == nullptr)
|
||||
return false;
|
||||
|
||||
std::time_t currTime = std::time(0);
|
||||
if (m_NextTimeToConnect > currTime)
|
||||
return false;
|
||||
|
||||
bool result = m_Pipe->Connect();
|
||||
if (result)
|
||||
LOG_INFO("Connected to pipe successfully.");
|
||||
else
|
||||
m_NextTimeToConnect = currTime + 5; // delay in 5 sec
|
||||
return result;
|
||||
}
|
23
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeClient.h
Normal file
23
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeClient.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
#include "PipeIO.h"
|
||||
|
||||
class PipeClient : public PipeIO
|
||||
{
|
||||
public:
|
||||
PipeClient() : PipeIO(), m_ConnectionDelay(5), m_NextTimeToConnect(0) {}
|
||||
|
||||
void SetConnectionDelay(uint32_t delay);
|
||||
uint32_t GetConnectionDelay();
|
||||
|
||||
bool IsConnected() final;
|
||||
void Connect(const std::string& pipeName);
|
||||
void Disconnect();
|
||||
|
||||
private:
|
||||
uint32_t m_ConnectionDelay;
|
||||
std::time_t m_NextTimeToConnect;
|
||||
|
||||
bool TryConnectToPipe();
|
||||
};
|
46
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.cpp
Normal file
46
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "PipeIO.h"
|
||||
|
||||
void PipeIO::Send(PipeMessage& data)
|
||||
{
|
||||
if (!IsConnected())
|
||||
return;
|
||||
|
||||
m_Pipe->WriteObject(data);
|
||||
}
|
||||
|
||||
PipeMessage* PipeIO::ReceiveMessage()
|
||||
{
|
||||
if (!IsConnected())
|
||||
return nullptr;
|
||||
|
||||
PipeMessage header;
|
||||
m_Pipe->ReadObject(header);
|
||||
|
||||
MessageIDs messageID = static_cast<MessageIDs>(header.packetID());
|
||||
|
||||
#define MESSAGE_CASE(mid, type)\
|
||||
case mid: \
|
||||
{ \
|
||||
auto data = new type(); \
|
||||
m_Pipe->ReadObject(*data); \
|
||||
data->SetMessage(header); \
|
||||
CallHandlers(*data); \
|
||||
return reinterpret_cast<PipeMessage*>(data); \
|
||||
}
|
||||
|
||||
switch (messageID)
|
||||
{
|
||||
MESSAGE_CASE(MessageIDs::PACKET_DATA, PipePacketData);
|
||||
MESSAGE_CASE(MessageIDs::MODIFY_DATA, PipeModifyData);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PipeIO::ProcessMessage()
|
||||
{
|
||||
auto message = ReceiveMessage();
|
||||
delete message;
|
||||
}
|
110
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.h
Normal file
110
cheat-library/src/user/cheat/misc/sniffer/pipe/PipeIO.h
Normal file
@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
#include "messages/PipeMessage.h"
|
||||
#include "messages/PipeModifyData.h"
|
||||
#include "messages/PipePacketData.h"
|
||||
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
|
||||
enum class MessageIDs : uint32_t
|
||||
{
|
||||
NONE = 0,
|
||||
PACKET_DATA = 1,
|
||||
MODIFY_DATA = 2
|
||||
};
|
||||
|
||||
namespace internal
|
||||
{
|
||||
template<class TMessage> struct message_to_id;
|
||||
template<> struct message_to_id<PipePacketData> : std::integral_constant<uint32_t, static_cast<uint32_t>(MessageIDs::PACKET_DATA)> {};
|
||||
template<> struct message_to_id<PipeModifyData> : std::integral_constant<uint32_t, static_cast<uint32_t>(MessageIDs::MODIFY_DATA)> {};
|
||||
}
|
||||
|
||||
class PipeIO
|
||||
{
|
||||
public:
|
||||
template<class T>
|
||||
using CallbackFunction = void(*)(const T& packetData);
|
||||
|
||||
template<class T>
|
||||
void AddHandler(CallbackFunction<T> callback)
|
||||
{
|
||||
static_assert(std::is_base_of<PipeMessage, T>::value, "Should be derived of MessageBase.");
|
||||
|
||||
constexpr auto messageID = internal::message_to_id<T>::value;
|
||||
|
||||
m_Handlers.push_back({
|
||||
messageID,
|
||||
reinterpret_cast<UniqueCallbackFunction>(callback)
|
||||
});
|
||||
}
|
||||
|
||||
template<class TMessage>
|
||||
TMessage CreateMessage(uint32_t reqID = 0, uint32_t seqID = 0)
|
||||
{
|
||||
static_assert(std::is_base_of<PipeMessage, TMessage>::value, "Should be derived of MessageBase.");
|
||||
|
||||
return TMessage(internal::message_to_id<TMessage>::value);
|
||||
}
|
||||
|
||||
template<class TMessage>
|
||||
std::optional<TMessage> WaitFor()
|
||||
{
|
||||
static_assert(std::is_base_of<PipeMessage, TMessage>::value, "Should be derived of MessageBase.");
|
||||
|
||||
if (!IsConnected())
|
||||
return {};
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto messagePtr = ReceiveMessage();
|
||||
if (messagePtr == nullptr)
|
||||
return {};
|
||||
|
||||
if (internal::message_to_id<TMessage>::value != messagePtr->packetID())
|
||||
{
|
||||
delete messagePtr;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Copying message
|
||||
TMessage message = *reinterpret_cast<TMessage*>(messagePtr);
|
||||
delete messagePtr;
|
||||
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
void Send(PipeMessage& data);
|
||||
|
||||
PipeMessage* ReceiveMessage();
|
||||
|
||||
void ProcessMessage();
|
||||
|
||||
virtual bool IsConnected() = 0;
|
||||
|
||||
protected:
|
||||
PipeIO() : m_Pipe(nullptr) {};
|
||||
PipeTransfer* m_Pipe;
|
||||
|
||||
private:
|
||||
using UniqueCallbackFunction = void(*)(const PipeMessage& pipeMessage);
|
||||
std::vector<std::pair<uint32_t, UniqueCallbackFunction>> m_Handlers;
|
||||
|
||||
template<class T>
|
||||
void CallHandlers(const T& message)
|
||||
{
|
||||
for (auto& [id, handler] : m_Handlers)
|
||||
{
|
||||
if (id == internal::message_to_id<T>::value)
|
||||
handler(message);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
PipeIO(PipeIO& other) = delete;
|
||||
PipeIO(PipeIO&& other) = delete;
|
||||
PipeIO& operator=(PipeIO& other) = delete;
|
||||
PipeIO& operator=(PipeIO&& other) = delete;
|
||||
};
|
@ -0,0 +1,37 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "PipeMessage.h"
|
||||
|
||||
PipeMessage::PipeMessage(uint32_t packetID) :
|
||||
m_PipePacketID(packetID), m_Timestamp(util::GetCurrentTimeMillisec())
|
||||
{ }
|
||||
|
||||
PipeMessage::PipeMessage() : m_PipePacketID(0), m_Timestamp(0)
|
||||
{ }
|
||||
|
||||
uint32_t PipeMessage::packetID() const
|
||||
{
|
||||
return m_PipePacketID;
|
||||
}
|
||||
|
||||
int64_t PipeMessage::timestamp() const
|
||||
{
|
||||
return m_Timestamp;
|
||||
}
|
||||
|
||||
void PipeMessage::Write(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Write(m_PipePacketID);
|
||||
transfer->Write(util::GetCurrentTimeMillisec());
|
||||
}
|
||||
|
||||
void PipeMessage::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read(m_PipePacketID);
|
||||
transfer->Read(m_Timestamp);
|
||||
}
|
||||
|
||||
void PipeMessage::SetMessage(const PipeMessage& other)
|
||||
{
|
||||
m_PipePacketID = other.m_PipePacketID;
|
||||
m_Timestamp = other.m_Timestamp;
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <atomic>
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
|
||||
class PipeMessage : public PipeSerializedObject
|
||||
{
|
||||
public:
|
||||
PipeMessage();
|
||||
PipeMessage(uint32_t packetID);
|
||||
uint32_t packetID() const;
|
||||
int64_t timestamp() const;
|
||||
|
||||
void SetMessage(const PipeMessage& other);
|
||||
void Write(PipeTransfer* transfer) override;
|
||||
void Read(PipeTransfer* transfer) override;
|
||||
|
||||
private:
|
||||
|
||||
uint32_t m_PipePacketID;
|
||||
int64_t m_Timestamp;
|
||||
};
|
@ -0,0 +1,32 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "PipeModifyData.h"
|
||||
|
||||
PipeModifyData::PipeModifyData() :
|
||||
modifyType(ModifyType::Unchanged), head({}), content({}), messageID(0)
|
||||
{ }
|
||||
|
||||
void PipeModifyData::Write(PipeTransfer* transfer)
|
||||
{
|
||||
PipeMessage::Write(transfer);
|
||||
|
||||
transfer->Write(modifyType);
|
||||
if (modifyType == ModifyType::Modified)
|
||||
{
|
||||
|
||||
transfer->Write(messageID);
|
||||
transfer->Write(content);
|
||||
transfer->Write(head);
|
||||
}
|
||||
}
|
||||
|
||||
void PipeModifyData::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read(modifyType);
|
||||
if (modifyType == ModifyType::Modified)
|
||||
{
|
||||
|
||||
transfer->Read(messageID);
|
||||
transfer->Read(content);
|
||||
transfer->Read(head);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
#include <cheat-base/PipeTransfer.h>
|
||||
#include "PipeMessage.h"
|
||||
|
||||
enum class ModifyType
|
||||
{
|
||||
Unchanged, Blocked, Modified
|
||||
};
|
||||
|
||||
class PipeModifyData : public PipeMessage
|
||||
{
|
||||
public:
|
||||
using PipeMessage::PipeMessage;
|
||||
|
||||
ModifyType modifyType;
|
||||
uint32_t messageID;
|
||||
std::vector<uint8_t> head;
|
||||
std::vector<uint8_t> content;
|
||||
|
||||
PipeModifyData();
|
||||
~PipeModifyData() {}
|
||||
|
||||
// Inherited via PipeSerializedObject
|
||||
virtual void Write(PipeTransfer* transfer) final;
|
||||
virtual void Read(PipeTransfer* transfer) final;
|
||||
};
|
@ -0,0 +1,22 @@
|
||||
#include "pch-il2cpp.h"
|
||||
#include "PipePacketData.h"
|
||||
|
||||
void PipePacketData::Write(PipeTransfer* transfer)
|
||||
{
|
||||
PipeMessage::Write(transfer);
|
||||
|
||||
transfer->Write(manipulationEnabled);
|
||||
transfer->Write(direction);
|
||||
transfer->Write(messageID);
|
||||
transfer->Write(head);
|
||||
transfer->Write(content);
|
||||
}
|
||||
|
||||
void PipePacketData::Read(PipeTransfer* transfer)
|
||||
{
|
||||
transfer->Read(manipulationEnabled);
|
||||
transfer->Read(direction);
|
||||
transfer->Read(messageID);
|
||||
transfer->Read(head);
|
||||
transfer->Read(content);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "PipeMessage.h"
|
||||
|
||||
enum class NetIODirection
|
||||
{
|
||||
Send, Receive
|
||||
};
|
||||
|
||||
class PipePacketData : public PipeMessage
|
||||
{
|
||||
public:
|
||||
using PipeMessage::PipeMessage;
|
||||
|
||||
bool manipulationEnabled;
|
||||
|
||||
NetIODirection direction;
|
||||
int16_t messageID;
|
||||
std::vector<byte> head;
|
||||
std::vector<byte> content;
|
||||
|
||||
// Inherited via PipeSerializedObject
|
||||
void Write(PipeTransfer* transfer) final;
|
||||
void Read(PipeTransfer* transfer) final;
|
||||
};
|
Loading…
Reference in New Issue
Block a user