mirror of
https://github.com/YimMenu/YimMenuV2.git
synced 2026-10-10 20:03:17 +08:00
feat(native_hooks): add native hooks
This commit is contained in:
@@ -17,6 +17,7 @@ namespace YimMenu
|
||||
BaseHook::Add<Hooks::SwapChain::ResizeBuffers>(new DetourHook("ResizeBuffers", swapchain_vft[Hooks::SwapChain::VMTResizeBuffersIdx], Hooks::SwapChain::ResizeBuffers));
|
||||
|
||||
BaseHook::Add<Hooks::Script::RunScriptThreads>(new DetourHook("RunScriptThreads", Pointers.RunScriptThreads, Hooks::Script::RunScriptThreads));
|
||||
BaseHook::Add<Hooks::Script::InitNativeTables>(new DetourHook("InitNativeTables", Pointers.InitNativeTables, Hooks::Script::InitNativeTables));
|
||||
|
||||
BaseHook::Add<Hooks::Info::AssignPhysicalIndex>(new DetourHook("AssignPhysicalIndex", Pointers.AssignPhysicalIndex, Hooks::Info::AssignPhysicalIndex));
|
||||
}
|
||||
|
||||
@@ -7,96 +7,97 @@
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
template<std::size_t N>
|
||||
class VMTHook : public BaseHook
|
||||
class VMTHook
|
||||
{
|
||||
private:
|
||||
std::string_view m_Name;
|
||||
bool m_Enabled;
|
||||
|
||||
std::array<void*, N> m_NewVMT = {nullptr};
|
||||
void** m_OriginalVMT;
|
||||
int m_NumEntries;
|
||||
void** m_NewVMT{};
|
||||
void** m_OriginalVMT{};
|
||||
void*** m_VMTAddress;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
VMTHook(const std::string_view name, T* vmtAddress);
|
||||
VMTHook(const std::string_view name, T* vmtAddress, int numEntries);
|
||||
~VMTHook();
|
||||
|
||||
virtual bool Enable() override;
|
||||
virtual bool Disable() override;
|
||||
VMTHook(VMTHook&& that) = delete;
|
||||
VMTHook& operator=(VMTHook&& that) = delete;
|
||||
VMTHook(VMTHook const&) = delete;
|
||||
VMTHook& operator=(VMTHook const&) = delete;
|
||||
|
||||
virtual void Enable();
|
||||
virtual void Disable();
|
||||
|
||||
template<typename T>
|
||||
inline T Original(const std::uint32_t idx) const;
|
||||
|
||||
template<typename T>
|
||||
void Hook(const std::uint32_t idx, T& detour);
|
||||
void Hook(const std::uint32_t idx, void* detour);
|
||||
void UnHook(const std::uint32_t idx);
|
||||
|
||||
inline constexpr std::size_t VMTSize() const
|
||||
{
|
||||
return N;
|
||||
return m_NumEntries;
|
||||
}
|
||||
};
|
||||
|
||||
template<std::size_t N>
|
||||
|
||||
template<typename T>
|
||||
inline VMTHook<N>::VMTHook(const std::string_view name, T* vmtAddress) :
|
||||
BaseHook(name),
|
||||
m_Enabled(false),
|
||||
m_VMTAddress(reinterpret_cast<void***>(vmtAddress))
|
||||
inline VMTHook::VMTHook(const std::string_view name, T* vmtAddress, int numEntries) :
|
||||
m_Name(name),
|
||||
m_VMTAddress(reinterpret_cast<void***>(vmtAddress)),
|
||||
m_NumEntries(numEntries),
|
||||
m_NewVMT(new void*[m_NumEntries]),
|
||||
m_Enabled(false)
|
||||
{
|
||||
m_OriginalVMT = *m_VMTAddress;
|
||||
std::copy_n(m_OriginalVMT, N, m_NewVMT.begin());
|
||||
memcpy(m_NewVMT, m_OriginalVMT, sizeof(void*) * m_NumEntries);
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
inline VMTHook<N>::~VMTHook()
|
||||
inline VMTHook::~VMTHook()
|
||||
{
|
||||
Disable();
|
||||
delete[] m_NewVMT;
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
inline bool VMTHook<N>::Enable()
|
||||
|
||||
inline void VMTHook::Enable()
|
||||
{
|
||||
if (m_Enabled)
|
||||
return false;
|
||||
return;
|
||||
|
||||
m_Enabled = true;
|
||||
*m_VMTAddress = m_NewVMT.data();
|
||||
return true;
|
||||
*m_VMTAddress = m_NewVMT;
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
inline bool VMTHook<N>::Disable()
|
||||
|
||||
inline void VMTHook::Disable()
|
||||
{
|
||||
if (!m_Enabled)
|
||||
return false;
|
||||
return;
|
||||
|
||||
*m_VMTAddress = m_OriginalVMT;
|
||||
m_Enabled = false;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
template<typename T>
|
||||
inline void VMTHook<N>::Hook(const std::uint32_t idx, T& detour)
|
||||
inline void VMTHook::Hook(const std::uint32_t idx, void* detour)
|
||||
{
|
||||
if (std::is_pointer<T>())
|
||||
m_NewVMT[idx] = reinterpret_cast<void*>(detour);
|
||||
else
|
||||
m_NewVMT[idx] = reinterpret_cast<void*>(&detour);
|
||||
m_NewVMT[idx] = reinterpret_cast<void*>(detour);
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
inline void VMTHook<N>::UnHook(const std::uint32_t idx)
|
||||
|
||||
inline void VMTHook::UnHook(const std::uint32_t idx)
|
||||
{
|
||||
m_NewVMT[idx] = m_OriginalVMT[idx];
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
|
||||
template<typename T>
|
||||
inline T VMTHook<N>::Original(const std::uint32_t idx) const
|
||||
inline T VMTHook::Original(const std::uint32_t idx) const
|
||||
{
|
||||
return reinterpret_cast<T>(m_OriginalVMT[idx]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "NativeHooks.hpp"
|
||||
|
||||
#include "game/gta/invoker/Invoker.hpp"
|
||||
|
||||
#include "types/script/scrProgram.hpp"
|
||||
#include "types/script/scrThread.hpp"
|
||||
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
NativeHooks::Program::Program(rage::scrProgram* program) :
|
||||
m_Program(program),
|
||||
m_Hook(std::make_unique<VMTHook>("rage::scrProgram", program, 9))
|
||||
{
|
||||
m_Hook->Hook(6, ScrProgram_Dtor);
|
||||
m_Hook->Enable();
|
||||
m_OrigHandlers = new rage::scrNativeHandler[program->m_NativeCount];
|
||||
memcpy(m_OrigHandlers, program->m_NativeEntrypoints, program->m_NativeCount * sizeof(rage::scrNativeHandler));
|
||||
}
|
||||
|
||||
void NativeHooks::Program::Apply(Hook hook)
|
||||
{
|
||||
auto old_native = NativeInvoker::GetNativeHandler(hook.m_Index);
|
||||
auto old_native_addr = m_Program->GetAddressOfNativeEntrypoint(old_native);
|
||||
if (old_native_addr)
|
||||
*old_native_addr = hook.m_Replacement;
|
||||
}
|
||||
|
||||
void NativeHooks::Program::Cleanup()
|
||||
{
|
||||
memcpy(m_Program->m_NativeEntrypoints, m_OrigHandlers, m_Program->m_NativeCount * sizeof(rage::scrNativeHandler));
|
||||
delete[] m_OrigHandlers;
|
||||
m_Hook->Disable();
|
||||
}
|
||||
|
||||
void NativeHooks::Program::ScrProgram_Dtor(rage::scrProgram* _this, bool free_mem)
|
||||
{
|
||||
NativeHooks::UnregisterProgram(_this);
|
||||
(**reinterpret_cast<decltype(&NativeHooks::Program::ScrProgram_Dtor)**>(_this))(_this, free_mem);
|
||||
}
|
||||
|
||||
NativeHooks::NativeHooks() :
|
||||
m_RegisteredPrograms(),
|
||||
m_RegisteredHooks()
|
||||
{
|
||||
m_RegisteredHooks.emplace(ALL_SCRIPTS, std::vector<Hook>());
|
||||
}
|
||||
|
||||
void NativeHooks::RunScriptImpl()
|
||||
{
|
||||
for (int i = 0; i < 176; i++)
|
||||
{
|
||||
if (Pointers.ScriptPrograms[i] != nullptr)
|
||||
RegisterProgram(Pointers.ScriptPrograms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeHooks::AddHookImpl(joaat_t script, NativeIndex index, rage::scrNativeHandler hook)
|
||||
{
|
||||
if (!g_Running)
|
||||
return;
|
||||
|
||||
if (auto it = m_RegisteredHooks.find(script); it != m_RegisteredHooks.end())
|
||||
{
|
||||
it->second.push_back(Hook(index, hook));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<Hook> hooks = {Hook(index, hook)};
|
||||
m_RegisteredHooks.emplace(script, hooks);
|
||||
}
|
||||
|
||||
for (auto& [scp, program] : m_RegisteredPrograms)
|
||||
{
|
||||
if (scp->m_NameHash == script || script == ALL_SCRIPTS)
|
||||
{
|
||||
program->Apply(Hook(index, hook));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NativeHooks::RegisterProgramImpl(rage::scrProgram* program)
|
||||
{
|
||||
if (!g_Running)
|
||||
return;
|
||||
|
||||
if (m_RegisteredPrograms.contains(program))
|
||||
{
|
||||
// LOG(FATAL) << "We've already registered " << program->m_Name << ". This is bad!";
|
||||
return;
|
||||
}
|
||||
|
||||
auto t = new Program(program);
|
||||
m_RegisteredPrograms.emplace(program, std::move(t));
|
||||
|
||||
auto& pgrm = m_RegisteredPrograms[program];
|
||||
|
||||
if (auto it = m_RegisteredHooks.find(program->m_NameHash); it != m_RegisteredHooks.end())
|
||||
{
|
||||
for (auto& hook : it->second)
|
||||
{
|
||||
pgrm->Apply(hook);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& hook : m_RegisteredHooks.at(ALL_SCRIPTS))
|
||||
{
|
||||
pgrm->Apply(hook);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeHooks::UnregisterProgramImpl(rage::scrProgram* program)
|
||||
{
|
||||
if (auto it = m_RegisteredPrograms.find(program); it != m_RegisteredPrograms.end())
|
||||
{
|
||||
it->second->Cleanup();
|
||||
m_RegisteredPrograms.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(FATAL) << "Cannot find program " << program->m_Name << " in registry. This is bad!";
|
||||
}
|
||||
}
|
||||
|
||||
void NativeHooks::DestroyImpl()
|
||||
{
|
||||
for (auto& [_, program] : m_RegisteredPrograms)
|
||||
program->Cleanup();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
#include "core/hooking/VMTHook.hpp"
|
||||
#include "core/util/Joaat.hpp"
|
||||
#include "types/script/scrNativeHandler.hpp"
|
||||
|
||||
enum class NativeIndex;
|
||||
|
||||
namespace rage
|
||||
{
|
||||
class scrProgram;
|
||||
}
|
||||
|
||||
namespace YimMenu
|
||||
{
|
||||
class NativeHooks
|
||||
{
|
||||
struct Hook
|
||||
{
|
||||
NativeIndex m_Index;
|
||||
rage::scrNativeHandler m_Replacement;
|
||||
};
|
||||
|
||||
class Program final
|
||||
{
|
||||
rage::scrProgram* m_Program = nullptr;
|
||||
std::unique_ptr<VMTHook> m_Hook = nullptr;
|
||||
rage::scrNativeHandler* m_OrigHandlers = nullptr;
|
||||
|
||||
public:
|
||||
Program(rage::scrProgram* program);
|
||||
void Apply(Hook hook);
|
||||
void Cleanup();
|
||||
static void ScrProgram_Dtor(rage::scrProgram* _this, bool free_mem);
|
||||
};
|
||||
|
||||
std::unordered_map<rage::scrProgram*, std::unique_ptr<Program>> m_RegisteredPrograms;
|
||||
std::unordered_map<joaat_t, std::vector<Hook>> m_RegisteredHooks;
|
||||
|
||||
public:
|
||||
static void RunScript()
|
||||
{
|
||||
GetInstance().RunScriptImpl();
|
||||
}
|
||||
|
||||
static constexpr auto ALL_SCRIPTS = "ALL_SCRIPTS"_J;
|
||||
static void AddHook(joaat_t script, NativeIndex index, rage::scrNativeHandler hook)
|
||||
{
|
||||
GetInstance().AddHookImpl(script, index, hook);
|
||||
}
|
||||
|
||||
static void RegisterProgram(rage::scrProgram* program)
|
||||
{
|
||||
GetInstance().RegisterProgramImpl(program);
|
||||
}
|
||||
|
||||
static void UnregisterProgram(rage::scrProgram* program)
|
||||
{
|
||||
GetInstance().UnregisterProgramImpl(program);
|
||||
}
|
||||
|
||||
static void Destroy()
|
||||
{
|
||||
GetInstance().DestroyImpl();
|
||||
}
|
||||
|
||||
private:
|
||||
NativeHooks();
|
||||
static NativeHooks& GetInstance()
|
||||
{
|
||||
static NativeHooks Instance;
|
||||
return Instance;
|
||||
}
|
||||
|
||||
void RunScriptImpl();
|
||||
void AddHookImpl(joaat_t script, NativeIndex index, rage::scrNativeHandler hook);
|
||||
void RegisterProgramImpl(rage::scrProgram* program);
|
||||
void UnregisterProgramImpl(rage::scrProgram* program);
|
||||
void DestroyImpl();
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "core/commands/BoolCommand.hpp"
|
||||
#include "game/backend/NativeHooks.hpp"
|
||||
#include "game/gta/Natives.hpp"
|
||||
#include "types/script/globals/GSBD.hpp"
|
||||
|
||||
namespace YimMenu::Features
|
||||
{
|
||||
static void BroadcastHook(rage::scrNativeCallContext* ctx);
|
||||
|
||||
class FastJoin : public BoolCommand
|
||||
{
|
||||
using BoolCommand::BoolCommand;
|
||||
|
||||
virtual void OnEnable() override
|
||||
{
|
||||
NativeHooks::AddHook("freemode"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
|
||||
NativeHooks::AddHook("fmmc_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
|
||||
NativeHooks::AddHook("am_launcher"_J, NativeIndex::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA, &BroadcastHook);
|
||||
}
|
||||
};
|
||||
|
||||
static FastJoin _FastJoin{"fastjoin", "Fast Join", "Attempts to improve join speed by loading host broadcast variables asynchronously. This may cause certain jobs to break, use with caution"};
|
||||
|
||||
static void BroadcastHook(rage::scrNativeCallContext* ctx)
|
||||
{
|
||||
if (!_FastJoin.GetState()
|
||||
|| NETWORK::NETWORK_IS_ACTIVITY_SESSION()
|
||||
|| NETWORK::NETWORK_IS_IN_TRANSITION()
|
||||
|| NETWORK::NETWORK_IS_TRANSITION_TO_GAME()
|
||||
|| NETWORK::NETWORK_IS_HOST_OF_THIS_SCRIPT()
|
||||
|| !STREAMING::IS_PLAYER_SWITCH_IN_PROGRESS()) // if there's no player switch, we're most likely loading into a job
|
||||
{
|
||||
return ctx->SetReturnValue(NETWORK::NETWORK_HAS_RECEIVED_HOST_BROADCAST_DATA());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SCRIPT::GET_HASH_OF_THIS_SCRIPT_NAME() == "freemode"_J)
|
||||
{
|
||||
GSBD::Get()->FreemodeState = eFreemodeState::RUNNING;
|
||||
GSBD::Get()->CayoPericoStrandedAnimalChoice = 0; // unbrick cayo just in case if the script host never responds
|
||||
}
|
||||
return ctx->SetReturnValue(TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,15 @@ namespace YimMenu::Submenus
|
||||
// TODO: this needs a rework
|
||||
auto session = std::make_shared<Category>("Session");
|
||||
auto toxicGroup = std::make_shared<Group>("Toxic");
|
||||
auto enhancements = std::make_shared<Group>("Enhancements");
|
||||
|
||||
toxicGroup->AddItem(std::make_shared<CommandItem>("killall"_J, "Kill All"));
|
||||
toxicGroup->AddItem(std::make_shared<CommandItem>("explodeall"_J, "Explode All"));
|
||||
|
||||
enhancements->AddItem(std::make_shared<BoolCommandItem>("fastjoin"_J));
|
||||
|
||||
session->AddItem(toxicGroup);
|
||||
session->AddItem(enhancements);
|
||||
|
||||
AddCategory(std::move(session));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include "Invoker.hpp"
|
||||
|
||||
#include "Crossmap.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
#include "core/hooking/DetourHook.hpp"
|
||||
#include "game/hooks/Hooks.hpp"
|
||||
|
||||
#include "types/script/scrProgram.hpp"
|
||||
|
||||
@@ -22,7 +23,7 @@ namespace YimMenu
|
||||
auto program = reinterpret_cast<rage::scrProgram*>(calloc(1, sizeof(rage::scrProgram)));
|
||||
program->m_NativeCount = m_Handlers.size();
|
||||
program->m_NativeEntrypoints = m_Handlers.data();
|
||||
Pointers.PopulateNatives(program);
|
||||
BaseHook::Get<Hooks::Script::InitNativeTables, DetourHook<decltype(&Hooks::Script::InitNativeTables)>>()->Original()(program);
|
||||
free(program);
|
||||
m_AreHandlersCached = true;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace rage
|
||||
{
|
||||
class netConnectionManager;
|
||||
class netEvent;
|
||||
class scrProgram;
|
||||
}
|
||||
|
||||
namespace YimMenu::Hooks
|
||||
@@ -27,6 +28,7 @@ namespace YimMenu::Hooks
|
||||
namespace Script
|
||||
{
|
||||
extern bool RunScriptThreads(int ops_to_execute);
|
||||
extern void InitNativeTables(rage::scrProgram* program);
|
||||
}
|
||||
|
||||
namespace Window
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "core/hooking/DetourHook.hpp"
|
||||
#include "game/backend/NativeHooks.hpp"
|
||||
#include "game/hooks/Hooks.hpp"
|
||||
|
||||
namespace YimMenu::Hooks
|
||||
{
|
||||
void Script::InitNativeTables(rage::scrProgram* program)
|
||||
{
|
||||
BaseHook::Get<Script::InitNativeTables, DetourHook<decltype(&Script::InitNativeTables)>>()->Original()(program);
|
||||
if (g_Running)
|
||||
{
|
||||
NativeHooks::RegisterProgram(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,9 +47,9 @@ namespace YimMenu
|
||||
ScriptThreads = ptr.Add(3).Rip().As<rage::atArray<rage::scrThread*>*>();
|
||||
});
|
||||
|
||||
constexpr auto populateNativesPtrn = Pattern<"EB 2A 0F 1F 40 00 48 8B 54 17 10">("PopulateNatives");
|
||||
constexpr auto populateNativesPtrn = Pattern<"EB 2A 0F 1F 40 00 48 8B 54 17 10">("InitNativeTables");
|
||||
scanner.Add(populateNativesPtrn, [this](PointerCalculator ptr) {
|
||||
PopulateNatives = ptr.Sub(0x2A).As<Functions::PopulateNatives>();
|
||||
InitNativeTables = ptr.Sub(0x2A).As<PVOID>();
|
||||
});
|
||||
|
||||
constexpr auto runScriptThreadsPtrn = Pattern<"BE 40 5D C6 00">("RunScriptThreads");
|
||||
@@ -93,6 +93,11 @@ namespace YimMenu
|
||||
TriggerWeaponDamageEvent = ptr.Sub(0x51).As<Functions::TriggerWeaponDamageEvent>();
|
||||
});
|
||||
|
||||
constexpr auto scriptProgramsPtrn = Pattern<"48 C7 84 C8 D8 00 00 00 00 00 00 00">("ScriptPrograms");
|
||||
scanner.Add(scriptProgramsPtrn, [this](PointerCalculator ptr) {
|
||||
ScriptPrograms = ptr.Add(0x13).Add(3).Rip().Add(0xD8).As<rage::scrProgram**>();
|
||||
});
|
||||
|
||||
if (!scanner.Scan())
|
||||
{
|
||||
LOG(FATAL) << "Some patterns could not be found, unloading.";
|
||||
|
||||
@@ -19,7 +19,6 @@ namespace YimMenu
|
||||
{
|
||||
namespace Functions
|
||||
{
|
||||
using PopulateNatives = void (*)(rage::scrProgram* program);
|
||||
using HandleToPtr = void* (*)(int handle);
|
||||
using PtrToHandle = int (*)(void* pointer);
|
||||
using GetNetPlayerFromPid = CNetGamePlayer* (*)(int id);
|
||||
@@ -35,7 +34,7 @@ namespace YimMenu
|
||||
std::uint32_t* ScreenResX;
|
||||
std::uint32_t* ScreenResY;
|
||||
rage::atArray<rage::scrThread*>* ScriptThreads;
|
||||
Functions::PopulateNatives PopulateNatives;
|
||||
PVOID InitNativeTables;
|
||||
std::int64_t** ScriptGlobals;
|
||||
PVOID RunScriptThreads;
|
||||
Functions::HandleToPtr HandleToPtr;
|
||||
@@ -45,6 +44,7 @@ namespace YimMenu
|
||||
bool* IsSessionStarted;
|
||||
PVOID AssignPhysicalIndex;
|
||||
Functions::TriggerWeaponDamageEvent TriggerWeaponDamageEvent;
|
||||
rage::scrProgram** ScriptPrograms;
|
||||
};
|
||||
|
||||
struct Pointers : PointerData
|
||||
|
||||
+8
-4
@@ -10,6 +10,7 @@
|
||||
#include "core/memory/ModuleMgr.hpp"
|
||||
#include "core/renderer/Renderer.hpp"
|
||||
#include "game/backend/Self.hpp"
|
||||
#include "game/backend/NativeHooks.hpp"
|
||||
#include "game/frontend/GUI.hpp"
|
||||
#include "game/pointers/Pointers.hpp"
|
||||
|
||||
@@ -26,13 +27,13 @@ namespace YimMenu
|
||||
Settings::Initialize(FileMgr::GetProjectFile("./settings.json"));
|
||||
|
||||
if (!ModuleMgr.LoadModules())
|
||||
goto unload;
|
||||
goto EARLY_UNLOAD;
|
||||
|
||||
if (!Pointers.Init())
|
||||
goto unload;
|
||||
goto EARLY_UNLOAD;
|
||||
|
||||
if (!Renderer::Init())
|
||||
goto unload;
|
||||
goto EARLY_UNLOAD;
|
||||
|
||||
Hooking::Init();
|
||||
|
||||
@@ -41,6 +42,7 @@ namespace YimMenu
|
||||
|
||||
GUI::Init();
|
||||
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&NativeHooks::RunScript)); // runs once
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&Self::RunScript));
|
||||
FiberPool::Init(5);
|
||||
ScriptMgr::AddScript(std::make_unique<Script>(&HotkeySystem::RunScript));
|
||||
@@ -54,11 +56,13 @@ namespace YimMenu
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
unload:
|
||||
LOG(INFO) << "Unloading";
|
||||
NativeHooks::Destroy();
|
||||
FiberPool::Destroy();
|
||||
ScriptMgr::Destroy();
|
||||
Hooking::Destroy();
|
||||
|
||||
EARLY_UNLOAD:
|
||||
Renderer::Destroy();
|
||||
LogHelper::Destroy();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user