错误:
`Assertion failed: IsInGameThread() || IsInSlateThread() [File:D:/UnrealEngines/UnrealEngine/Engine/Source/Runtime/SlateCore/Private/Widgets/SWidget.cpp] [Line: 1119] Slate can only be accessed from the GameThread or the SlateLoadingThread!
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
JH_Win64_Shipping
UE4_ProcessEvent!JhSDK::UObject::ProcessEvent() [D:\项目\UE4_ProcessEvent\UE4_ProcessEvent\JhSDK.h:545]
UE4_ProcessEvent!JhSDK::UItemManager::AddItem() [D:\项目\UE4_ProcessEvent\UE4_ProcessEvent\JhSDK.h:1316]
UE4_ProcessEvent!HackThread() [D:\项目\UE4_ProcessEvent\UE4_ProcessEvent\dllmain.cpp:72]`
解释:这个错误信息指出在尝试访问 Unreal Engine 的 Slate UI 系统时违反了线程安全规则。Slate UI 组件只能在游戏线程(GameThread)或 Slate 加载线程(SlateLoadingThread)上被访问或修改。
在你的代码中,你似乎在一个名为 HackThread 的线程中调用了与 Slate 相关的代码(可能是通过 JhSDK::UItemManager::AddItem() 方法),而这个线程并不是 Unreal Engine 所允许的线程之一。
解决方法:
1. 使用FTimerDelegate
FTimerDelegate 可以用于在指定的延迟后执行一个委托(delegate),并且这个执行是在游戏线程上进行的。虽然这不是直接的消息队列,但它可以作为一种延迟执行任务的方式。
FTimerHandle timerHandle;
GetWorld()->GetTimerManager().SetTimer(
timerHandle,
FTimerDelegate::CreateLambda([&]()
{
// 这里是你要在游戏线程上执行的代码
}),
0.0f, // 立即执行
false // 不重复
);
2.Hook FEngineLoop::Tick
该函数在游戏主线程内,负责处理游戏逻辑、用户输入、物理模拟、动画更新等核心游戏功能。它也是其他线程的数据发起者,并在每帧的更新中执行逻辑更新。
特征:
x64dbg搜索
Tick loop starting
3.Hook PostRender
typedef void(__fastcall* tPostRender)(JhSDK::UGameViewportClient* viewport_client, JhSDK::UCanvas* canvas);
static tPostRender hkPostRender = nullptr;
void RenderText(JhSDK::UCanvas* Canvas,JhSDK::FVector2D Position,JhSDK::FString text,JhSDK::FLinearColor color) {
Canvas->K2_DrawText(engine_font, text, Position, {1.f,1.f}, color, false, {0.0f,0.0f,0.0f,1.f}, {0.0f,0.0f}, false, false, true, color);
}
void HookedPostRender(JhSDK::UGameViewportClient* viewport_client, JhSDK::UCanvas* canvas)
{
RenderText(canvas, { 150.f,150.f }, L"[#] Hello From PostRender", { 1.f,0.0f,1.f,1.f });
if (GetAsyncKeyState(VK_F1) & 1) {
ManagerFuncLib->ItemManager->AddItem(1, 1, JhSDK::EItemRandPoolType::Normal);
}
return hkPostRender(viewport_client, canvas);
}
auto localPlayer = (*JhSDK::m_UWorld)->PersistentLevel->OwningWorld->
OwningGameInstance->LocalPlayers.Data[0];
world_peh.ApplyHook((uintptr_t)localPlayer->ViewportClient, (std::uintptr_t*)&hkPostRender, (std::uintptr_t)HookedPostRender,0x62);