Плохой рендер CEF

nonelike

Известный
Автор темы
58
2
plugin.hpp:
#ifndef PLUGIN_HPP
#define PLUGIN_HPP

#include <windows.h>

#include <kthook/kthook.hpp>
#include <RakHook/rakhook.hpp>

#include "overlay.hpp"

using namespace std::placeholders;


class c_plugin {

public:
    c_plugin() = default;
    ~c_plugin() { rakhook::destroy(); render::destroy(); overlay::destroy(); };

    kthook::kthook_simple<void(__cdecl*)()> update_hook { reinterpret_cast<void*>(0x561B10), std::bind(&c_plugin::update_hooked, this, _1) };
    void update_hooked(const decltype(update_hook)& hook);

    kthook::kthook_simple<HRESULT(__stdcall*)(HWND, UINT, WPARAM, LPARAM)> wnd_proc_hook{ reinterpret_cast<void*>(0x747EB0), std::bind(&c_plugin::wnd_proc_hooked, this, _1, _2, _3, _4, _5) };
    HRESULT wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
};


#endif // PLUGIN_HPP
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>

#include "include/cef_app.h"
#include "render.hpp"


class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {

public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
 
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 840, 660); };
 
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};


namespace overlay {
    inline static c_overlay* cef;

    inline LPDIRECT3DTEXTURE9 texture;

    void initialize();
 
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);

    void destroy();
}


#endif // !OVERLAY_HPP
plugin.cpp:
#include "plugin.hpp"


void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
     
        overlay::initialize();
        render::initialize();
     
        render::on_present += []() {
            if (!overlay::texture || !render::device)
                return;

            render::device->SetTexture(0, overlay::texture);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                FLOAT u, v;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));
        };
    }
    return hook.call_trampoline();
}


HRESULT c_plugin::wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    overlay::wnd_proc(hwnd, umsg, wp, lp);

    return hook.call_trampoline(hwnd, umsg, wp, lp);
}

overlay.cpp:
#include "overlay.hpp"


void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (!overlay::texture)
        D3DXCreateTexture(render::device, width, height, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &overlay::texture);

    D3DLOCKED_RECT locked_rect;
 
    overlay::texture->LockRect(0, &locked_rect, nullptr, 0);
    memcpy(locked_rect.pBits, buffer, width * height * 4);

    overlay::texture->UnlockRect(0);
}


void overlay::create_browser(std::string url) {
    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    window_info.SetAsWindowless(nullptr);
 
    CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}


void overlay::initialize() {
    cef = new c_overlay();
 
    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cache");

    CefSettings settings;
 
    CefString(&settings.browser_subprocess_path).FromASCII(std::string(work_path + "\\cef-sub-process.exe").c_str());
    CefString(&settings.log_file) = work_path + "\\cef-log.log";
    CefString(&settings.cache_path).FromASCII(std::string(work_path + "\\cache").c_str());
    CefString(&settings.locales_dir_path).FromASCII(std::string(work_path + "\\locales").c_str());
    CefString(&settings.resources_dir_path) = work_path;
    CefString(&settings.locale).FromASCII("ru");
    CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");

    settings.no_sandbox = 1;
    settings.multi_threaded_message_loop = 1;
    settings.windowless_rendering_enabled = 1;

    settings.background_color = 0;
    settings.log_severity = LOGSEVERITY_DEBUG;
    settings.command_line_args_disabled = 1;

    CefMainArgs main_args;

    CefInitialize(main_args, settings, nullptr, nullptr);
 
    create_browser();
}


bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (cef && cef->GetBrowser()) {
        CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

        if (umsg >= WM_MOUSEMOVE && umsg <= WM_MBUTTONUP || umsg == WM_MOUSEWHEEL) {
            POINT point = { LOWORD(lp), HIWORD(lp) };
            ScreenToClient(hwnd, &point);

            CefMouseEvent mouse_event;
         
            mouse_event.x = point.x;
            mouse_event.y = point.y;
            mouse_event.modifiers = 0;

            switch (umsg) {
                case WM_LBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1); break;
                case WM_LBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1); break;
                case WM_RBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1); break;
                case WM_RBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1); break;
                case WM_MBUTTONDOWN: host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, false, 1); break;
                case WM_MBUTTONUP:   host->SendMouseClickEvent(mouse_event, MBT_MIDDLE, true, 1); break;
                case WM_MOUSEWHEEL: {
                    int delta = GET_WHEEL_DELTA_WPARAM(wp);
                    host->SendMouseWheelEvent(mouse_event, 0, delta);
                    break;
                }
                default: {
                    host->SendMouseMoveEvent(mouse_event, false);
                    break;
                }
            }
            return true;
        }

        if (umsg >= WM_KEYDOWN && umsg <= WM_CHAR) {
            int keycode = static_cast<int>(wp);
            int modifiers = 0;

            if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
            if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
            if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;

            CefKeyEvent event;
         
            event.windows_key_code = keycode;
            event.native_key_code = static_cast<int>(lp);
            event.modifiers = modifiers;

            if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) { event.type = KEYEVENT_RAWKEYDOWN; }
            else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) { event.type = KEYEVENT_KEYUP; }
            else if (umsg == WM_CHAR) { event.type = KEYEVENT_CHAR; }

            host->SendKeyEvent(event);

            return true;
        }
    }
    return false;
}


void overlay::destroy() {
    CefShutdown();
 
    if (texture)
        texture->Release();
 
    delete cef;
}

main.cpp:
#include "plugin.hpp"

c_plugin* plugin;


int __stdcall DllMain(HMODULE instance, DWORD call_reason, LPVOID reserved) {

    if (call_reason == DLL_PROCESS_ATTACH) {
        DisableThreadLibraryCalls(instance);

        plugin = new c_plugin();
    }
    else if (call_reason == DLL_PROCESS_DETACH)
        delete plugin;

    return TRUE;
}

render.hpp:
#ifndef RENDER_HPP
#define RENDER_HPP

#include <imgui_impl_dx9.h>
#include <imgui_impl_win32.h>
#include <imgui_internal.h>

#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

#include "kthook/kthook.hpp"

#include "samp.hpp"


namespace render {
    template <typename T>
    struct on_event : public std::vector<std::function<T>> {
        on_event& operator+=(std::function<T> func) {
            this->push_back(func);
            return *this;
        }
    };
    inline on_event<void()> on_present;

    inline bool initialized = false;

    inline IDirect3DDevice9* device;

    void initialize();
    void destroy();
}

#endif // !RENDER_HPP

render.cpp:
#include "render.hpp"
#include "overlay.hpp"

kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*)> present_hook;
kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*)> reset_hook;


std::optional<HRESULT> d3d9_present_hooked(const decltype(present_hook)& hook, IDirect3DDevice9* device, CONST RECT* src_rect, CONST RECT* dest_rect, HWND dest_window, CONST RGNDATA* dirty_region) {
    if (!render::initialized) {
        render::device = device;
        render::initialized = true;
    }
    else {
        for (auto& f : render::on_present) {
            if (f) f();
        }
    }
    return std::nullopt;
}


std::optional<HRESULT> d3d9_lost_hooked(const decltype(reset_hook)& hook, LPDIRECT3DDEVICE9 device, D3DPRESENT_PARAMETERS* present_params) {
    return std::nullopt;
}


uintptr_t find_device(uint32_t length) {
    static uintptr_t base = [](size_t length) {
        std::string path(MAX_PATH, '\0');

        if (auto size = GetSystemDirectoryA(path.data(), MAX_PATH)) {
            path.resize(size);
            path += "\\d3d9.dll";

            uintptr_t object_base = reinterpret_cast<uintptr_t>(LoadLibraryA(path.c_str()));

            while (object_base++ < object_base + length) {
                if (*reinterpret_cast<uint16_t*>(object_base + 0x00) == 0x06C7 && *reinterpret_cast<uint16_t*>(object_base + 0x06) == 0x8689 && *reinterpret_cast<uint16_t*>(object_base + 0x0C) == 0x8689) {
                    object_base += 2;

                    break;
                }
            }
            return object_base;
        }
        return uintptr_t(0);
    }(length);

    return base;
}


void* get_function_address(int virtual_table_index) {
    return (*reinterpret_cast<void***>(find_device(0x128000)))[virtual_table_index];
}


void render::initialize() {
    present_hook.set_dest(get_function_address(17));
    present_hook.install();
 
    reset_hook.set_dest(get_function_address(16));
    reset_hook.install();

    present_hook.before.connect(&d3d9_present_hooked);
    reset_hook.before.connect(&d3d9_lost_hooked);
}


void render::destroy() {
}

Увидел как-то на форуме CEF который отрисовывается на imgui, решил переделать в отрисовку через directx9, но плохо рендерится(текст, мыло и все пикселится, появляется черная обводка которой нет) и ломает ESC.
 

Вложения

  • sa-mp-010.png
    sa-mp-010.png
    71.6 KB · Просмотры: 193
  • sa-mp-009.png
    sa-mp-009.png
    1.2 MB · Просмотры: 190

vmprotect

Известный
389
252
насчет фикса рендеринга

в overlay.hpp ты указываешь размер

Код:
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 1920, 1080); }; /* на месте 1920, 1080 указывать свое разрешение

ваще можно через imgui получать твое текущее разрешение, и туда вписывать
 

nonelike

Известный
Автор темы
58
2
насчет фикса рендеринга

в overlay.hpp ты указываешь размер

Код:
void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 1920, 1080); }; /* на месте 1920, 1080 указывать свое разрешение

ваще можно через imgui получать твое текущее разрешение, и туда вписывать
ну я ща в GetViewRect поменял на свое разрешение монитора, и в вершинах тоже, но чето рендеру все равно плохо
 

Вложения

  • sa-mp-012.png
    sa-mp-012.png
    1.7 MB · Просмотры: 162
Последнее редактирование:

dmitry.karle

Известный
363
100
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
 
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
                const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
        rect = CefRect(0, 0, 840, 660);
    };
 
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;

    void initialize();
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP

overlay.cpp:
#include "overlay.hpp"

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height) {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }
      
        if (D3DXCreateTexture(render::device, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &overlay::texture) == D3D_OK) {
            overlay::texture_width = width;
            overlay::texture_height = height;
        } else {
            return;
        }
    }

    D3DLOCKED_RECT locked_rect;
    if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
        for (int y = 0; y < height; ++y) {
            const uint8_t* src = static_cast<const uint8_t*>(buffer) + y * width * 4;
            uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits) + y * locked_rect.Pitch;
            memcpy(dst, src, width * 4);
        }
        overlay::texture->UnlockRect(0);
    }
}

void overlay::create_browser(std::string url) {
    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;
  
    browser_settings.windowless_frame_rate = 60;
    window_info.SetAsWindowless(nullptr);
 
    CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}

void overlay::initialize() {
    cef = new c_overlay();
 
    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cache");

    CefSettings settings;
    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000; // Fully transparent
  
    CefString(&settings.browser_subprocess_path).FromASCII((work_path + "\\cef-sub-process.exe").c_str());
    CefString(&settings.cache_path).FromASCII((work_path + "\\cache").c_str());
    CefString(&settings.locales_dir_path).FromASCII((work_path + "\\locales").c_str());
    CefString(&settings.resources_dir_path) = work_path;
    CefString(&settings.locale).FromASCII("ru");
    CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");

    CefMainArgs main_args;
    CefInitialize(main_args, settings, nullptr, nullptr);
 
    create_browser();
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser())
        return false;

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { LOWORD(lp), HIWORD(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
      
        if (umsg == WM_MOUSEWHEEL) {
            int delta = GET_WHEEL_DELTA_WPARAM(wp);
            host->SendMouseWheelEvent(mouse_event, 0, delta);
            return true;
        }
      
        if (umsg >= WM_LBUTTONDOWN && umsg <= WM_MBUTTONUP) {
            cef_mouse_button_type_t button = MBT_LEFT;
            if (umsg == WM_RBUTTONDOWN || umsg == WM_RBUTTONUP) button = MBT_RIGHT;
            else if (umsg == WM_MBUTTONDOWN || umsg == WM_MBUTTONUP) button = MBT_MIDDLE;
          
            bool is_up = (umsg == WM_LBUTTONUP || umsg == WM_RBUTTONUP || umsg == WM_MBUTTONUP);
            host->SendMouseClickEvent(mouse_event, button, is_up, 1);
            return true;
        }
      
        host->SendMouseMoveEvent(mouse_event, false);
        return true;
    }

    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
      
        event.modifiers = 0;
        if (GetKeyState(VK_SHIFT) & 0x8000) event.modifiers |= EVENTFLAG_SHIFT_DOWN;
        if (GetKeyState(VK_CONTROL) & 0x8000) event.modifiers |= EVENTFLAG_CONTROL_DOWN;
        if (GetKeyState(VK_MENU) & 0x8000) event.modifiers |= EVENTFLAG_ALT_DOWN;
      
        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }
      
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false; // Let the game process ESC
        }
      
        host->SendKeyEvent(event);
        return true;
    }
  
    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }
  
    CefShutdown();
    delete cef;
    cef = nullptr;
}

plugin.cpp:
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();
  
        render::on_present += []() {
            if (!overlay::texture || !render::device)
                return;

            DWORD old_z_enable, old_alpha_blend, old_src_blend, old_dest_blend, old_lighting;
            render::device->GetRenderState(D3DRS_ZENABLE, &old_z_enable);
            render::device->GetRenderState(D3DRS_ALPHABLENDENABLE, &old_alpha_blend);
            render::device->GetRenderState(D3DRS_SRCBLEND, &old_src_blend);
            render::device->GetRenderState(D3DRS_DESTBLEND, &old_dest_blend);
            render::device->GetRenderState(D3DRS_LIGHTING, &old_lighting);

            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);

            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT u, v;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->SetTexture(0, overlay::texture);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            render::device->SetRenderState(D3DRS_ZENABLE, old_z_enable);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, old_alpha_blend);
            render::device->SetRenderState(D3DRS_SRCBLEND, old_src_blend);
            render::device->SetRenderState(D3DRS_DESTBLEND, old_dest_blend);
            render::device->SetRenderState(D3DRS_LIGHTING, old_lighting);
        };
    }
    return hook.call_trampoline();
}
проверь и исправь под себя😐
 
Последнее редактирование:

nonelike

Известный
Автор темы
58
2
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override { this->browser = browser; }
 
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
                const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
        rect = CefRect(0, 0, 840, 660);
    };
 
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;

    void initialize();
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP

overlay.cpp:
#include "overlay.hpp"

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height) {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }
   
        if (D3DXCreateTexture(render::device, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &overlay::texture) == D3D_OK) {
            overlay::texture_width = width;
            overlay::texture_height = height;
        } else {
            return;
        }
    }

    D3DLOCKED_RECT locked_rect;
    if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
        for (int y = 0; y < height; ++y) {
            const uint8_t* src = static_cast<const uint8_t*>(buffer) + y * width * 4;
            uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits) + y * locked_rect.Pitch;
            memcpy(dst, src, width * 4);
        }
        overlay::texture->UnlockRect(0);
    }
}

void overlay::create_browser(std::string url) {
    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;
 
    browser_settings.windowless_frame_rate = 60;
    window_info.SetAsWindowless(nullptr);
 
    CefBrowserHost::CreateBrowser(window_info, cef, url.c_str(), browser_settings, nullptr, nullptr);
}

void overlay::initialize() {
    cef = new c_overlay();
 
    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cache");

    CefSettings settings;
    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000; // Fully transparent
 
    CefString(&settings.browser_subprocess_path).FromASCII((work_path + "\\cef-sub-process.exe").c_str());
    CefString(&settings.cache_path).FromASCII((work_path + "\\cache").c_str());
    CefString(&settings.locales_dir_path).FromASCII((work_path + "\\locales").c_str());
    CefString(&settings.resources_dir_path) = work_path;
    CefString(&settings.locale).FromASCII("ru");
    CefString(&settings.accept_language_list).FromASCII("en-US,en,ru-RU,ru");

    CefMainArgs main_args;
    CefInitialize(main_args, settings, nullptr, nullptr);
 
    create_browser();
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser())
        return false;

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { LOWORD(lp), HIWORD(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
   
        if (umsg == WM_MOUSEWHEEL) {
            int delta = GET_WHEEL_DELTA_WPARAM(wp);
            host->SendMouseWheelEvent(mouse_event, 0, delta);
            return true;
        }
   
        if (umsg >= WM_LBUTTONDOWN && umsg <= WM_MBUTTONUP) {
            cef_mouse_button_type_t button = MBT_LEFT;
            if (umsg == WM_RBUTTONDOWN || umsg == WM_RBUTTONUP) button = MBT_RIGHT;
            else if (umsg == WM_MBUTTONDOWN || umsg == WM_MBUTTONUP) button = MBT_MIDDLE;
       
            bool is_up = (umsg == WM_LBUTTONUP || umsg == WM_RBUTTONUP || umsg == WM_MBUTTONUP);
            host->SendMouseClickEvent(mouse_event, button, is_up, 1);
            return true;
        }
   
        host->SendMouseMoveEvent(mouse_event, false);
        return true;
    }

    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
   
        event.modifiers = 0;
        if (GetKeyState(VK_SHIFT) & 0x8000) event.modifiers |= EVENTFLAG_SHIFT_DOWN;
        if (GetKeyState(VK_CONTROL) & 0x8000) event.modifiers |= EVENTFLAG_CONTROL_DOWN;
        if (GetKeyState(VK_MENU) & 0x8000) event.modifiers |= EVENTFLAG_ALT_DOWN;
   
        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }
   
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false; // Let the game process ESC
        }
   
        host->SendKeyEvent(event);
        return true;
    }
 
    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }
 
    CefShutdown();
    delete cef;
    cef = nullptr;
}

plugin.cpp:
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();
 
        render::on_present += []() {
            if (!overlay::texture || !render::device)
                return;

            DWORD old_z_enable, old_alpha_blend, old_src_blend, old_dest_blend, old_lighting;
            render::device->GetRenderState(D3DRS_ZENABLE, &old_z_enable);
            render::device->GetRenderState(D3DRS_ALPHABLENDENABLE, &old_alpha_blend);
            render::device->GetRenderState(D3DRS_SRCBLEND, &old_src_blend);
            render::device->GetRenderState(D3DRS_DESTBLEND, &old_dest_blend);
            render::device->GetRenderState(D3DRS_LIGHTING, &old_lighting);

            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);

            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT u, v;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->SetTexture(0, overlay::texture);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            render::device->SetRenderState(D3DRS_ZENABLE, old_z_enable);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, old_alpha_blend);
            render::device->SetRenderState(D3DRS_SRCBLEND, old_src_blend);
            render::device->SetRenderState(D3DRS_DESTBLEND, old_dest_blend);
            render::device->SetRenderState(D3DRS_LIGHTING, old_lighting);
        };
    }
    return hook.call_trampoline();
}
проверь и исправь под себя😐
чето все равно ему плохо моментами
 

Вложения

  • sa-mp-019.png
    sa-mp-019.png
    207.4 KB · Просмотры: 93
  • 2.jpg
    2.jpg
    66.3 KB · Просмотры: 89
Последнее редактирование:

dmitry.karle

Известный
363
100
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
        this->browser = browser;
        browser->GetHost()->SetWindowlessFrameRate(60); --для фпса
    }
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 840, 660); };
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;
    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;
    inline bool needs_update = false;
    void initialize();
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP


plugin.cpp:
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();
    
        render::on_present += []() {
            if (!overlay::texture || !render::device || !overlay::needs_update)
                return;

            // сохранения состояния
            D3DVIEWPORT9 old_viewport;
            IDirect3DStateBlock9* state_block = nullptr;
            render::device->CreateStateBlock(D3DSBT_ALL, &state_block);
            render::device->GetViewport(&old_viewport);

            // параметры для рендера
            D3DVIEWPORT9 viewport = {0, 0, 840, 660, 0.0f, 1.0f};
            render::device->SetViewport(&viewport);
            
            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
            render::device->SetRenderState(D3DRS_ALPHAREF, 0x08);
            render::device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);
            render::device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
            render::device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);

            render::device->SetTexture(0, overlay::texture);
            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
            render::device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
            render::device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT tu, tv;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            if (state_block) {
                state_block->Apply();
                state_block->Release();
            }
            render::device->SetViewport(&old_viewport);
            overlay::needs_update = false;
        };
    }
    return hook.call_trampoline();
}


cpp:
#include "overlay.hpp"
#include <d3dx9.h>

namespace overlay {
    inline static c_overlay* cef = nullptr;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;
    inline bool needs_update = false;
    inline bool browser_created = false;
}

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    // two check and buffer
    if (width <= 0 || height <= 0 || !buffer || !render::device) {
        return;
    }

    // check and update texture
    bool texture_needs_update = false;
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height) {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }

        HRESULT hr = D3DXCreateTexture(
            render::device,
            width,
            height,
            1,
            D3DUSAGE_DYNAMIC,
            D3DFMT_A8R8G8B8,
            D3DPOOL_DEFAULT,
            &overlay::texture
        );

        if (FAILED(hr) {
            return;
        }

        overlay::texture_width = width;
        overlay::texture_height = height;
        texture_needs_update = true;
    }

    // update texture
    D3DLOCKED_RECT locked_rect;
    if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
        const uint8_t* src = static_cast<const uint8_t*>(buffer);
        uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits);

        if (locked_rect.Pitch == width * 4) {
            memcpy(dst, src, width * height * 4);
        } else {
            for (int y = 0; y < height; ++y) {
                memcpy(dst, src, width * 4);
                src += width * 4;
                dst += locked_rect.Pitch;
            }
        }

        overlay::texture->UnlockRect(0);
        overlay::needs_update = true;
    }
}

void overlay::create_browser(std::string url) {
    if (browser_created) return;

    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    browser_settings.windowless_frame_rate = 60;
    browser_settings.background_color = 0x00000000;
    browser_settings.webgl = STATE_DISABLED;
    browser_settings.plugins = STATE_DISABLED;

    window_info.SetAsWindowless(nullptr);
    window_info.shared_texture_enabled = false;
    window_info.external_begin_frame_enabled = false;

    CefBrowserHost::CreateBrowser(
        window_info,
        cef,
        url,
        browser_settings,
        nullptr,
        nullptr
    );

    browser_created = true;
}

void overlay::initialize() {
    if (cef) return;

    CefMainArgs main_args(GetModuleHandle(nullptr));
    CefSettings settings;

    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cef_cache");

    CefString(&settings.browser_subprocess_path).FromString(work_path + "\\cef_subprocess.exe");
    CefString(&settings.cache_path).FromString(work_path + "\\cef_cache");
    CefString(&settings.locales_dir_path).FromString(work_path + "\\locales");
    CefString(&settings.resources_dir_path).FromString(work_path);
    CefString(&settings.locale).FromString("ru");
    CefString(&settings.accept_language_list).FromString("ru-RU,ru,en-US,en");

    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000;
    settings.log_severity = LOGSEVERITY_DISABLE;
    settings.command_line_args_disabled = true;
    settings.pack_loading_disabled = false;

    if (!CefInitialize(main_args, settings, nullptr, nullptr)) {
        return;
    }

    cef = new c_overlay();
    create_browser();
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser()) {
        return false;
    }

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    // обработка мыши
    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
        mouse_event.modifiers = GetCefModifiers();

        switch (umsg) {
            case WM_MOUSEMOVE:
                host->SendMouseMoveEvent(mouse_event, false);
                return true;
            case WM_LBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
                return true;
            case WM_LBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
                return true;
            case WM_RBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
                return true;
            case WM_RBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
                return true;
            case WM_MOUSEWHEEL:
                host->SendMouseWheelEvent(mouse_event, 0, GET_WHEEL_DELTA_WPARAM(wp));
                return true;
        }
    }

    // обработка клавы
    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
        event.modifiers = GetCefModifiers();

        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }

        // esc
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false;
        }

        host->SendKeyEvent(event);
        return true;
    }

    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }

    if (cef) {
        if (cef->GetBrowser()) {
            cef->GetBrowser()->GetHost()->CloseBrowser(true);
        }
        delete cef;
        cef = nullptr;
    }

    CefShutdown();
}

// help func or modification
int GetCefModifiers() {
    int modifiers = 0;
    if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
    if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
    if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;
    if (GetKeyState(VK_CAPITAL) & 0x0001) modifiers |= EVENTFLAG_CAPS_LOCK_ON;
    return modifiers;
}
хз, проверь это, 3 cpp полностью переписан и должен быть улучшенный рендер
 

nonelike

Известный
Автор темы
58
2
overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
        this->browser = browser;
        browser->GetHost()->SetWindowlessFrameRate(60); --для фпса
    }
    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override { rect = CefRect(0, 0, 840, 660); };
    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;
    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;
    inline bool needs_update = false;
    void initialize();
    void create_browser(std::string url = "https://url.com");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP


plugin.cpp:
void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();
   
        render::on_present += []() {
            if (!overlay::texture || !render::device || !overlay::needs_update)
                return;

            // сохранения состояния
            D3DVIEWPORT9 old_viewport;
            IDirect3DStateBlock9* state_block = nullptr;
            render::device->CreateStateBlock(D3DSBT_ALL, &state_block);
            render::device->GetViewport(&old_viewport);

            // параметры для рендера
            D3DVIEWPORT9 viewport = {0, 0, 840, 660, 0.0f, 1.0f};
            render::device->SetViewport(&viewport);
           
            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
            render::device->SetRenderState(D3DRS_ALPHAREF, 0x08);
            render::device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);
            render::device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
            render::device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);

            render::device->SetTexture(0, overlay::texture);
            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
            render::device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
            render::device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT tu, tv;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            if (state_block) {
                state_block->Apply();
                state_block->Release();
            }
            render::device->SetViewport(&old_viewport);
            overlay::needs_update = false;
        };
    }
    return hook.call_trampoline();
}


cpp:
#include "overlay.hpp"
#include <d3dx9.h>

namespace overlay {
    inline static c_overlay* cef = nullptr;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;
    inline bool needs_update = false;
    inline bool browser_created = false;
}

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    // two check and buffer
    if (width <= 0 || height <= 0 || !buffer || !render::device) {
        return;
    }

    // check and update texture
    bool texture_needs_update = false;
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height) {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }

        HRESULT hr = D3DXCreateTexture(
            render::device,
            width,
            height,
            1,
            D3DUSAGE_DYNAMIC,
            D3DFMT_A8R8G8B8,
            D3DPOOL_DEFAULT,
            &overlay::texture
        );

        if (FAILED(hr) {
            return;
        }

        overlay::texture_width = width;
        overlay::texture_height = height;
        texture_needs_update = true;
    }

    // update texture
    D3DLOCKED_RECT locked_rect;
    if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
        const uint8_t* src = static_cast<const uint8_t*>(buffer);
        uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits);

        if (locked_rect.Pitch == width * 4) {
            memcpy(dst, src, width * height * 4);
        } else {
            for (int y = 0; y < height; ++y) {
                memcpy(dst, src, width * 4);
                src += width * 4;
                dst += locked_rect.Pitch;
            }
        }

        overlay::texture->UnlockRect(0);
        overlay::needs_update = true;
    }
}

void overlay::create_browser(std::string url) {
    if (browser_created) return;

    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    browser_settings.windowless_frame_rate = 60;
    browser_settings.background_color = 0x00000000;
    browser_settings.webgl = STATE_DISABLED;
    browser_settings.plugins = STATE_DISABLED;

    window_info.SetAsWindowless(nullptr);
    window_info.shared_texture_enabled = false;
    window_info.external_begin_frame_enabled = false;

    CefBrowserHost::CreateBrowser(
        window_info,
        cef,
        url,
        browser_settings,
        nullptr,
        nullptr
    );

    browser_created = true;
}

void overlay::initialize() {
    if (cef) return;

    CefMainArgs main_args(GetModuleHandle(nullptr));
    CefSettings settings;

    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cef_cache");

    CefString(&settings.browser_subprocess_path).FromString(work_path + "\\cef_subprocess.exe");
    CefString(&settings.cache_path).FromString(work_path + "\\cef_cache");
    CefString(&settings.locales_dir_path).FromString(work_path + "\\locales");
    CefString(&settings.resources_dir_path).FromString(work_path);
    CefString(&settings.locale).FromString("ru");
    CefString(&settings.accept_language_list).FromString("ru-RU,ru,en-US,en");

    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000;
    settings.log_severity = LOGSEVERITY_DISABLE;
    settings.command_line_args_disabled = true;
    settings.pack_loading_disabled = false;

    if (!CefInitialize(main_args, settings, nullptr, nullptr)) {
        return;
    }

    cef = new c_overlay();
    create_browser();
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser()) {
        return false;
    }

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    // обработка мыши
    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
        mouse_event.modifiers = GetCefModifiers();

        switch (umsg) {
            case WM_MOUSEMOVE:
                host->SendMouseMoveEvent(mouse_event, false);
                return true;
            case WM_LBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
                return true;
            case WM_LBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
                return true;
            case WM_RBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
                return true;
            case WM_RBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
                return true;
            case WM_MOUSEWHEEL:
                host->SendMouseWheelEvent(mouse_event, 0, GET_WHEEL_DELTA_WPARAM(wp));
                return true;
        }
    }

    // обработка клавы
    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
        event.modifiers = GetCefModifiers();

        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }

        // esc
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false;
        }

        host->SendKeyEvent(event);
        return true;
    }

    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }

    if (cef) {
        if (cef->GetBrowser()) {
            cef->GetBrowser()->GetHost()->CloseBrowser(true);
        }
        delete cef;
        cef = nullptr;
    }

    CefShutdown();
}

// help func or modification
int GetCefModifiers() {
    int modifiers = 0;
    if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
    if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
    if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;
    if (GetKeyState(VK_CAPITAL) & 0x0001) modifiers |= EVENTFLAG_CAPS_LOCK_ON;
    return modifiers;
}
хз, проверь это, 3 cpp полностью переписан и должен быть улучшенный рендер
теперь крашится игра, вижу на секунду что текстурка начинает рисоваться белая, а после игра крашится, на всякий случай приложу код, мб чето не так копипастнул
render.hpp:
#ifndef RENDER_HPP
#define RENDER_HPP

#include <imgui_impl_dx9.h>
#include <imgui_impl_win32.h>
#include <imgui_internal.h>

#include <d3d9.h>
#include <d3dx9.h>

#pragma comment (lib, "d3d9.lib")
#pragma comment (lib, "d3dx9.lib")

#include "kthook/kthook.hpp"

#include "samp.hpp"


namespace render {
    template <typename T>
    struct on_event : public std::vector<std::function<T>> {
        on_event& operator+=(std::function<T> func) {
            this->push_back(func);
            return *this;
        }
    };
    inline on_event<void()> on_present;

    inline bool initialized = false;

    inline IDirect3DDevice9* device;

    void initialize();
    void destroy();
}

#endif // !RENDER_HPP

plugin.hpp:
#ifndef PLUGIN_HPP
#define PLUGIN_HPP

#include <windows.h>

#include <kthook/kthook.hpp>
#include <RakHook/rakhook.hpp>

#include "overlay.hpp"

using namespace std::placeholders;


class c_plugin {

public:
    c_plugin() = default;
    ~c_plugin() { rakhook::destroy(); render::destroy(); overlay::destroy(); };

    kthook::kthook_simple<void(__cdecl*)()> update_hook { reinterpret_cast<void*>(0x561B10), std::bind(&c_plugin::update_hooked, this, _1) };
    void update_hooked(const decltype(update_hook)& hook);

    kthook::kthook_simple<HRESULT(__stdcall*)(HWND, UINT, WPARAM, LPARAM)> wnd_proc_hook{ reinterpret_cast<void*>(0x747EB0), std::bind(&c_plugin::wnd_proc_hooked, this, _1, _2, _3, _4, _5) };
    HRESULT wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
};


#endif // PLUGIN_HPP

overlay.hpp:
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <filesystem>
#include <include/cef_app.h>
#include "render.hpp"
#include <windowsx.h>

class c_overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    c_overlay() = default;
    ~c_overlay() = default;

    virtual CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; };
    virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
        this->browser = browser;
        browser->GetHost()->SetWindowlessFrameRate(60);
    }

    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type,
        const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override {
        rect = CefRect(0, 0, 840, 660);
    };

    CefRefPtr<CefBrowser> GetBrowser() { return this->browser; };

private:
    CefRefPtr<CefBrowser> browser;

    IMPLEMENT_REFCOUNTING(c_overlay);
    DISALLOW_COPY_AND_ASSIGN(c_overlay);
};

namespace overlay {
    inline static c_overlay* cef;
    inline LPDIRECT3DTEXTURE9 texture = nullptr;
    inline int texture_width = 0;
    inline int texture_height = 0;
    inline bool needs_update = false;
    inline bool browser_created = false;

    void initialize();
    void create_browser(std::string url = "file:///C:/Bounce.html");
    bool wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp);
    void destroy();
}

#endif // !OVERLAY_HPP

plugin.cpp:
#include "plugin.hpp"


void c_plugin::update_hooked(const decltype(update_hook)& hook) {
    static bool inited = false;

    if (!inited && c_chat().reference() && rakhook::initialize()) {
        inited = true;
        overlay::initialize();
        render::initialize();

        render::on_present += []() {
            if (!overlay::texture || !render::device || !overlay::needs_update)
            {
                OutputDebugString("!overlay");
            }

            // сохранения состояния
            D3DVIEWPORT9 old_viewport;
            IDirect3DStateBlock9* state_block = nullptr;
            render::device->CreateStateBlock(D3DSBT_ALL, &state_block);
            render::device->GetViewport(&old_viewport);

            // параметры для рендера
            D3DVIEWPORT9 viewport = { 0, 0, 840, 660, 0.0f, 1.0f };
            render::device->SetViewport(&viewport);

            render::device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
            render::device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
            render::device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
            render::device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
            render::device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
            render::device->SetRenderState(D3DRS_ALPHAREF, 0x08);
            render::device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
            render::device->SetRenderState(D3DRS_LIGHTING, FALSE);
            render::device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
            render::device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);

            render::device->SetTexture(0, overlay::texture);
            render::device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
            render::device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
            render::device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
            render::device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

            struct CUSTOMVERTEX {
                FLOAT x, y, z, rhw;
                DWORD color;
                FLOAT tu, tv;
            };

            CUSTOMVERTEX vertices[] = {
                { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
            };

            render::device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
            render::device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices, sizeof(CUSTOMVERTEX));

            if (state_block) {
                state_block->Apply();
                state_block->Release();
            }
            render::device->SetViewport(&old_viewport);
            overlay::needs_update = false;
            };
    }
    return hook.call_trampoline();
}

HRESULT c_plugin::wnd_proc_hooked(const decltype(wnd_proc_hook)& hook, HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    overlay::wnd_proc(hwnd, umsg, wp, lp);

    return hook.call_trampoline(hwnd, umsg, wp, lp);
}

overlay.cpp:
#include "overlay.hpp"
#include <d3dx9.h>

void c_overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    // two check and buffer
    if (width <= 0 || height <= 0 || !buffer || !render::device) {
        return;
    }

    // check and update texture
    bool texture_needs_update = false;
    if (!overlay::texture || width != overlay::texture_width || height != overlay::texture_height)
    {
        if (overlay::texture) {
            overlay::texture->Release();
            overlay::texture = nullptr;
        }

        HRESULT hr = D3DXCreateTexture(
            render::device,
            width,
            height,
            1,
            D3DUSAGE_DYNAMIC,
            D3DFMT_A8R8G8B8,
            D3DPOOL_DEFAULT,
            &overlay::texture
        );

        if (FAILED(hr))
        {
            OutputDebugString("failed hr");
        }

        overlay::texture_width = width;
        overlay::texture_height = height;
        texture_needs_update = true;
    }

    // update texture
    D3DLOCKED_RECT locked_rect;
        if (overlay::texture->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD) == D3D_OK) {
            const uint8_t* src = static_cast<const uint8_t*>(buffer);
            uint8_t* dst = static_cast<uint8_t*>(locked_rect.pBits);

            if (locked_rect.Pitch == width * 4) {
                memcpy(dst, src, width * height * 4);
            }
            else {
                for (int y = 0; y < height; ++y) {
                    memcpy(dst, src, width * 4);
                    src += width * 4;
                    dst += locked_rect.Pitch;
                }
            }

            overlay::texture->UnlockRect(0);
            overlay::needs_update = true;
        }
}

void overlay::create_browser(std::string url) {
    if (browser_created)
    {
        OutputDebugString("created browser");
    }

    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    browser_settings.windowless_frame_rate = 60;
    browser_settings.background_color = 0x00000000;
    browser_settings.webgl = STATE_DISABLED;

    window_info.SetAsWindowless(nullptr);
    window_info.shared_texture_enabled = false;
    window_info.external_begin_frame_enabled = false;

    CefBrowserHost::CreateBrowser(
        window_info,
        cef,
        url,
        browser_settings,
        nullptr,
        nullptr
    );

    browser_created = true;
}

void overlay::initialize() {
    if (cef)
    {
        OutputDebugString("cef ");
    }

    CefMainArgs main_args(GetModuleHandle(nullptr));
    CefSettings settings;

    std::string work_path = std::filesystem::current_path().string();
    std::filesystem::create_directories(work_path + "\\cef_cache");

    CefString(&settings.browser_subprocess_path).FromString(work_path + "\\cef_subprocess.exe");
    CefString(&settings.cache_path).FromString(work_path + "\\cef_cache");
    CefString(&settings.locales_dir_path).FromString(work_path + "\\locales");
    CefString(&settings.resources_dir_path).FromString(work_path);
    CefString(&settings.locale).FromString("ru");
    CefString(&settings.accept_language_list).FromString("ru-RU,ru,en-US,en");

    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000;
    settings.log_severity = LOGSEVERITY_DISABLE;
    settings.command_line_args_disabled = true;

    if (!CefInitialize(main_args, settings, nullptr, nullptr)) {
        OutputDebugString("cefinit");
    }

    cef = new c_overlay();
    create_browser();
}

int GetCefModifiers() {
    int modifiers = 0;
    if (GetKeyState(VK_SHIFT) & 0x8000) modifiers |= EVENTFLAG_SHIFT_DOWN;
    if (GetKeyState(VK_CONTROL) & 0x8000) modifiers |= EVENTFLAG_CONTROL_DOWN;
    if (GetKeyState(VK_MENU) & 0x8000) modifiers |= EVENTFLAG_ALT_DOWN;
    if (GetKeyState(VK_CAPITAL) & 0x0001) modifiers |= EVENTFLAG_CAPS_LOCK_ON;
    return modifiers;
}

bool overlay::wnd_proc(HWND hwnd, UINT umsg, WPARAM wp, LPARAM lp) {
    if (!cef || !cef->GetBrowser()) {
        OutputDebugString("return false");
        return false;
    }

    CefRefPtr<CefBrowserHost> host = cef->GetBrowser()->GetHost();

    // обработка мыши
    if (umsg >= WM_MOUSEFIRST && umsg <= WM_MOUSELAST) {
        POINT point = { GET_X_LPARAM(lp), GET_Y_LPARAM(lp) };
        ScreenToClient(hwnd, &point);

        CefMouseEvent mouse_event;
        mouse_event.x = point.x;
        mouse_event.y = point.y;
        mouse_event.modifiers = GetCefModifiers();

        switch (umsg) {
        case WM_MOUSEMOVE:
            host->SendMouseMoveEvent(mouse_event, false);
            return true;
        case WM_LBUTTONDOWN:
            host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
            return true;
        case WM_LBUTTONUP:
            host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
            return true;
        case WM_RBUTTONDOWN:
            host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
            return true;
        case WM_RBUTTONUP:
            host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
            return true;
        case WM_MOUSEWHEEL:
            host->SendMouseWheelEvent(mouse_event, 0, GET_WHEEL_DELTA_WPARAM(wp));
            return true;
        }
    }

    // обработка клавы
    if (umsg >= WM_KEYFIRST && umsg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wp);
        event.native_key_code = static_cast<int>(lp);
        event.modifiers = GetCefModifiers();

        if (umsg == WM_KEYDOWN || umsg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        }
        else if (umsg == WM_KEYUP || umsg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        }
        else if (umsg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }

        // esc
        if (event.windows_key_code == VK_ESCAPE && event.type == KEYEVENT_RAWKEYDOWN) {
            return false;
        }

        host->SendKeyEvent(event);
        return true;
    }

    return false;
}

void overlay::destroy() {
    if (texture) {
        texture->Release();
        texture = nullptr;
    }

    if (cef) {
        if (cef->GetBrowser()) {
            cef->GetBrowser()->GetHost()->CloseBrowser(true);
        }
        delete cef;
        cef = nullptr;
    }

    CefShutdown();
}

render.cpp:
#include "render.hpp"
#include "overlay.hpp"

kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*)> present_hook;
kthook::kthook_signal<HRESULT(__stdcall*)(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*)> reset_hook;


std::optional<HRESULT> d3d9_present_hooked(const decltype(present_hook)& hook, IDirect3DDevice9* device, CONST RECT* src_rect, CONST RECT* dest_rect, HWND dest_window, CONST RGNDATA* dirty_region) {
    if (!render::initialized) {
        render::device = device;
        render::initialized = true;
    }
    else {
        for (auto& f : render::on_present) {
            if (f) f();
        }
    }
    return std::nullopt;
}


std::optional<HRESULT> d3d9_lost_hooked(const decltype(reset_hook)& hook, LPDIRECT3DDEVICE9 device, D3DPRESENT_PARAMETERS* present_params) {
    return std::nullopt;
}


uintptr_t find_device(uint32_t length) {
    static uintptr_t base = [](size_t length) {
        std::string path(MAX_PATH, '\0');

        if (auto size = GetSystemDirectoryA(path.data(), MAX_PATH)) {
            path.resize(size);
            path += "\\d3d9.dll";

            uintptr_t object_base = reinterpret_cast<uintptr_t>(LoadLibraryA(path.c_str()));

            while (object_base++ < object_base + length) {
                if (*reinterpret_cast<uint16_t*>(object_base + 0x00) == 0x06C7 && *reinterpret_cast<uint16_t*>(object_base + 0x06) == 0x8689 && *reinterpret_cast<uint16_t*>(object_base + 0x0C) == 0x8689) {
                    object_base += 2;

                    break;
                }
            }
            return object_base;
        }
        return uintptr_t(0);
    }(length);

    return base;
}


void* get_function_address(int virtual_table_index) {
    return (*reinterpret_cast<void***>(find_device(0x128000)))[virtual_table_index];
}


void render::initialize() {
    present_hook.set_dest(get_function_address(17));
    present_hook.install();
    
    reset_hook.set_dest(get_function_address(16));
    reset_hook.install();

    present_hook.before.connect(&d3d9_present_hooked);
    reset_hook.before.connect(&d3d9_lost_hooked);
}


void render::destroy() {
}
 

dmitry.karle

Известный
363
100
render.hpp:
#pragma once
#ifndef RENDER_HPP
#define RENDER_HPP

#include <d3d9.h>
#include <d3dx9.h>
#include <atomic>
#include <mutex>
#include <functional>
#include <vector>
#include <memory>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")

class IDirect3DDevice9;

namespace render {
    class EventSystem {
    public:
        using Callback = std::function<void()>;
       
        void subscribe(Callback&& cb) {
            std::lock_guard<std::mutex> lock(mutex_);
            callbacks_.emplace_back(std::move(cb));
        }

        void notify() {
            std::vector<Callback> local_copy;
            {
                std::lock_guard<std::mutex> lock(mutex_);
                local_copy = callbacks_;
            }
           
            for (auto& cb : local_copy) {
                if (cb) cb();
            }
        }

    private:
        std::mutex mutex_;
        std::vector<Callback> callbacks_;
    };

    class DeviceManager {
    public:
        static DeviceManager& instance() {
            static DeviceManager inst;
            return inst;
        }

        bool initialize(IDirect3DDevice9* device);
        void shutdown();
       
        IDirect3DDevice9* device() const {
            std::lock_guard<std::mutex> lock(device_mutex_);
            return device_;
        }

        bool is_initialized() const {
            return initialized_.load(std::memory_order_acquire);
        }

    private:
        DeviceManager() = default;
        ~DeviceManager() = default;

        mutable std::mutex device_mutex_;
        IDirect3DDevice9* device_{nullptr};
        std::atomic<bool> initialized_{false};
    };

    extern EventSystem on_present;
}

#endif


render.cpp:
#include "render.hpp"
#include <kthook/kthook.hpp>

namespace render {
    namespace {
        class D3DHooks {
        public:
            D3DHooks() {
                present_hook_.set_callback([](auto&& hook, auto&&... args) {
                    auto& dm = DeviceManager::instance();
                    if (!dm.is_initialized()) {
                        dm.initialize(std::get<0>(std::forward_as_tuple(args...)));
                    }
                    on_present.notify();
                    return hook.call_trampoline(std::forward<decltype(args)>(args)...);
                });

                reset_hook_.set_callback([](auto&& hook, auto&&... args) {
                    DeviceManager::instance().shutdown();
                    return hook.call_trampoline(std::forward<decltype(args)>(args)...);
                });

                if (auto d3d9 = GetModuleHandle("d3d9.dll")) {
                    present_hook_.install(GetProcAddress(d3d9, "Direct3DCreate9"));
                    reset_hook_.install(GetProcAddress(d3d9, "Direct3DCreate9"));
                }
            }

            ~D3DHooks() = default;

        private:
            kthook::kthook_signal<HRESULT(IDirect3DDevice9*, const RECT*, const RECT*, HWND, const RGNDATA*)> present_hook_;
            kthook::kthook_signal<HRESULT(IDirect3DDevice9*, D3DPRESENT_PARAMETERS*)> reset_hook_;
        };

        std::unique_ptr<D3DHooks> hooks;
    }

    EventSystem on_present;

    bool DeviceManager::initialize(IDirect3DDevice9* device) {
        std::lock_guard<std::mutex> lock(device_mutex_);
        if (initialized_) return true;

        device_ = device;
        device_->AddRef();
        initialized_.store(true, std::memory_order_release);
       
        if (!hooks) {
            hooks = std::make_unique<D3DHooks>();
        }

        return true;
    }

    void DeviceManager::shutdown() {
        std::lock_guard<std::mutex> lock(device_mutex_);
        if (device_) {
            device_->Release();
            device_ = nullptr;
        }
        initialized_.store(false, std::memory_order_release);
    }
}


overlay.hpp:
#pragma once
#ifndef OVERLAY_HPP
#define OVERLAY_HPP

#include <include/cef_app.h>
#include <include/cef_client.h>
#include <include/cef_render_handler.h>
#include <include/cef_life_span_handler.h>
#include <atomic>
#include <memory>
#include <mutex>
#include "render.hpp"

class Overlay : public CefClient, public CefRenderHandler, public CefLifeSpanHandler {
public:
    Overlay();
    ~Overlay() override;

    CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }
    CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }

    void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;

    void OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) override;
    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override;

    CefRefPtr<CefBrowser> browser() const { return browser_; }

private:
    CefRefPtr<CefBrowser> browser_;
   
    IMPLEMENT_REFCOUNTING(Overlay);
    DISALLOW_COPY_AND_ASSIGN(Overlay);
};

class OverlaySystem {
public:
    static OverlaySystem& instance();

    bool initialize();
    void shutdown();
   
    bool create_browser(const std::string& url);
    bool process_message(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);

    bool is_initialized() const { return initialized_.load(); }
    bool is_browser_created() const { return browser_created_.load(); }

private:
    OverlaySystem() = default;
    ~OverlaySystem() = default;

    std::mutex mutex_;
    std::unique_ptr<Overlay> overlay_;
    IDirect3DTexture9* texture_{nullptr};
    std::atomic<int> texture_width_{0};
    std::atomic<int> texture_height_{0};
    std::atomic<bool> needs_update_{false};
    std::atomic<bool> initialized_{false};
    std::atomic<bool> browser_created_{false};
};

#endif


overlay.cpp:
#include "overlay.hpp"
#include <d3dx9.h>
#include <windowsx.h>
#include <array>

namespace {
    int get_cef_modifiers() {
        std::array modifiers = {
            std::make_pair(VK_SHIFT, EVENTFLAG_SHIFT_DOWN),
            std::make_pair(VK_CONTROL, EVENTFLAG_CONTROL_DOWN),
            std::make_pair(VK_MENU, EVENTFLAG_ALT_DOWN),
            std::make_pair(VK_CAPITAL, EVENTFLAG_CAPS_LOCK_ON)
        };

        int result = 0;
        for (const auto& [key, flag] : modifiers) {
            if (GetKeyState(key) & 0x8000) {
                result |= flag;
            }
        }
        return result;
    }
}

Overlay::Overlay() = default;
Overlay::~Overlay() {
    if (browser_) {
        browser_->GetHost()->CloseBrowser(true);
    }
}

void Overlay::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
    browser_ = browser;
    browser_->GetHost()->SetWindowlessFrameRate(60);
    OverlaySystem::instance().is_browser_created().store(true);
}

void Overlay::OnPaint(CefRefPtr<CefBrowser> browser, PaintElementType type, const RectList& dirty_rects, const void* buffer, int width, int height) {
    if (width <= 0 || height <= 0 || !buffer) return;

    auto& system = OverlaySystem::instance();
    auto* device = render::DeviceManager::instance().device();
    if (!device) return;

    std::lock_guard<std::mutex> lock(system.mutex_);

    if (!system.texture_ || width != system.texture_width_ || height != system.texture_height_) {
        if (system.texture_) {
            system.texture_->Release();
            system.texture_ = nullptr;
        }

        if (FAILED(D3DXCreateTexture(device, width, height, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &system.texture_))) {
            return;
        }

        system.texture_width_ = width;
        system.texture_height_ = height;
    }

    D3DLOCKED_RECT locked_rect;
    if (SUCCEEDED(system.texture_->LockRect(0, &locked_rect, nullptr, D3DLOCK_DISCARD))) {
        const auto* src = static_cast<const uint8_t*>(buffer);
        auto* dst = static_cast<uint8_t*>(locked_rect.pBits);

        if (locked_rect.Pitch == width * 4) {memcpy(dst, src, width * height * 4);
        } else {
            for (int y = 0; y < height; ++y) {
                memcpy(dst, src, width * 4);
                src += width * 4;
                dst += locked_rect.Pitch;
            }
        }

        system.texture_->UnlockRect(0);
        system.needs_update_ = true;
    }
}

void Overlay::GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) {
    rect = CefRect(0, 0, 840, 660);
}

OverlaySystem& OverlaySystem::instance() {
    static OverlaySystem inst;
    return inst;
}

bool OverlaySystem::initialize() {
    if (initialized_) return true;

    CefMainArgs main_args(GetModuleHandle(nullptr));
    CefSettings settings;

    settings.windowless_rendering_enabled = true;
    settings.no_sandbox = true;
    settings.multi_threaded_message_loop = true;
    settings.background_color = 0x00000000;
    settings.log_severity = LOGSEVERITY_DISABLE;

    if (!CefInitialize(main_args, settings, nullptr, nullptr)) {
        return false;
    }

    overlay_ = std::make_unique<Overlay>();
    initialized_.store(true);
    return true;
}

void OverlaySystem::shutdown() {
    std::lock_guard<std::mutex> lock(mutex_);
   
    if (texture_) {
        texture_->Release();
        texture_ = nullptr;
    }

    if (overlay_) {
        overlay_.reset();
    }

    if (initialized_) {
        CefShutdown();
        initialized_.store(false);
    }
}

bool OverlaySystem::create_browser(const std::string& url) {
    if (!initialized_ || browser_created_) return false;

    CefWindowInfo window_info;
    CefBrowserSettings browser_settings;

    browser_settings.windowless_frame_rate = 60;
    browser_settings.background_color = 0x00000000;
    browser_settings.webgl = STATE_DISABLED;

    window_info.SetAsWindowless(nullptr);
    window_info.shared_texture_enabled = false;
    window_info.external_begin_frame_enabled = false;

    return CefBrowserHost::CreateBrowser(window_info, overlay_.get(), url, browser_settings, nullptr, nullptr);
}

bool OverlaySystem::process_message(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    if (!browser_created_ || !overlay_ || !overlay_->browser()) {
        return false;
    }

    auto host = overlay_->browser()->GetHost();
    if (!host) return false;

    if (msg >= WM_MOUSEFIRST && msg <= WM_MOUSELAST) {
        POINT pt = { GET_X_LPARAM(lparam), GET_Y_LPARAM(lparam) };
        ScreenToClient(hwnd, &pt);

        CefMouseEvent mouse_event;
        mouse_event.x = pt.x;
        mouse_event.y = pt.y;
        mouse_event.modifiers = get_cef_modifiers();

        switch (msg) {
            case WM_MOUSEMOVE:
                host->SendMouseMoveEvent(mouse_event, false);
                return true;
            case WM_LBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, false, 1);
                return true;
            case WM_LBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_LEFT, true, 1);
                return true;
            case WM_RBUTTONDOWN:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, false, 1);
                return true;
            case WM_RBUTTONUP:
                host->SendMouseClickEvent(mouse_event, MBT_RIGHT, true, 1);
                return true;
            case WM_MOUSEWHEEL:
                host->SendMouseWheelEvent(mouse_event, 0, GET_WHEEL_DELTA_WPARAM(wparam));
                return true;
        }
    }

    if (msg >= WM_KEYFIRST && msg <= WM_KEYLAST) {
        CefKeyEvent event;
        event.windows_key_code = static_cast<int>(wparam);
        event.native_key_code = static_cast<int>(lparam);
        event.modifiers = get_cef_modifiers();

        if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) {
            event.type = KEYEVENT_RAWKEYDOWN;
        } else if (msg == WM_KEYUP || msg == WM_SYSKEYUP) {
            event.type = KEYEVENT_KEYUP;
        } else if (msg == WM_CHAR) {
            event.type = KEYEVENT_CHAR;
        }

        host->SendKeyEvent(event);
        return true;
    }

    return false;
}


plugin.hpp:
#pragma once
#ifndef PLUGIN_HPP
#define PLUGIN_HPP

#include <windows.h>
#include <kthook/kthook.hpp>
#include <RakHook/rakhook.hpp>
#include "overlay.hpp"

class Plugin {
public:Plugin(); ~Plugin();

private:
    void update_hooked(const kthook::kthook_simple<void()>& hook);
    HRESULT wnd_proc_hooked(const kthook::kthook_simple<HRESULT(HWND, UINT, WPARAM, LPARAM)>& hook, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);

    kthook::kthook_simple<void()> update_hook_;
    kthook::kthook_simple<HRESULT(HWND, UINT, WPARAM, LPARAM)> wnd_proc_hook_;
    bool initialized_{false};
};

#endif


plugin.cpp:
#include "plugin.hpp"
#include "render.hpp"

Plugin::Plugin() :
    update_hook_(reinterpret_cast<void*>(0x561B10)),
    wnd_proc_hook_(reinterpret_cast<void*>(0x747EB0)) {
   
    update_hook_.set_callback([this](auto&& hook) { update_hooked(hook); });
    wnd_proc_hook_.set_callback([this](auto&& hook, auto&&... args) {
        return wnd_proc_hooked(hook, std::forward<decltype(args)>(args)...);
    });
}

Plugin::~Plugin() {
    rakhook::destroy();
    OverlaySystem::instance().shutdown();
    render::DeviceManager::instance().shutdown();
}

void Plugin::update_hooked(const kthook::kthook_simple<void()>& hook) {
    if (!initialized_ && c_chat().reference() && rakhook::initialize()) {
        initialized_ = true;
       
        if (OverlaySystem::instance().initialize()) {
            OverlaySystem::instance().create_browser("data:text/html,<h1>Loading...</h1>");
           
            render::on_present.subscribe([]() {
                auto& overlay = OverlaySystem::instance();
                auto* device = render::DeviceManager::instance().device();
               
                if (!overlay.is_browser_created() || !device || !overlay.texture_) {
                    return;
                }

                IDirect3DStateBlock9* state_block = nullptr;
                if (FAILED(device->CreateStateBlock(D3DSBT_ALL, &state_block))) {
                    return;
                }

                device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
                device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
                device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
                device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
                device->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
                device->SetRenderState(D3DRS_ALPHAREF, 0x08);
                device->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
                device->SetRenderState(D3DRS_LIGHTING, FALSE);
                device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
                device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);

                device->SetTexture(0, overlay.texture_);
                device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
                device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
                device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
                device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
                device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
                device->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
                device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
                device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

                struct Vertex {
                    FLOAT x, y, z, rhw;
                    DWORD color;
                    FLOAT tu, tv;
                };

                const std::array<Vertex, 4> vertices = {{
                    { 0.0f,   0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
                    { 840.0f, 0.0f,   0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 0.0f },
                    { 0.0f,   660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 1.0f },
                    { 840.0f, 660.0f, 0.0f, 1.0f, 0xFFFFFFFF, 1.0f, 1.0f }
                }};

                device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
                device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, vertices.data(), sizeof(Vertex));

                if (state_block) {
                    state_block->Apply();
                    state_block->Release();
                }
            });
        }
    }
    hook.call_trampoline();
}

HRESULT Plugin::wnd_proc_hooked(const kthook::kthook_simple<HRESULT(HWND, UINT, WPARAM, LPARAM)>& hook, HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
    if (OverlaySystem::instance().process_message(hwnd, msg, wparam, lparam)) {
        return TRUE;
    }
    return hook.call_trampoline(hwnd, msg, wparam, lparam);
}

в прошлом там реально косяк с пастой (проверок нет, косяк в обработке буфера), проверь этот вариант или вернись к прошлой версии которая работает и там надо искать проблему с рендером